summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Kling <anton@kling.gg>2023-10-22 19:50:38 +0200
committerAnton Kling <anton@kling.gg>2023-10-22 19:50:38 +0200
commit4e09bca9e34c226b6d7e34b4fa11248405fd988e (patch)
tree80f156b7940d9d19971395f335530170c69516c7
Move everything into a new repo.
-rw-r--r--.clang-format1
-rw-r--r--.gitignore26
-rw-r--r--COPYING674
-rw-r--r--LICENSE14
-rw-r--r--Makefile33
-rw-r--r--README.md35
-rw-r--r--arch/i386/boot.s128
-rw-r--r--arch/i386/mmu.c565
-rw-r--r--cpu/gdt.c72
-rw-r--r--cpu/gdt.h76
-rw-r--r--cpu/idt.c265
-rw-r--r--cpu/idt.h76
-rw-r--r--cpu/int_syscall.s20
-rw-r--r--cpu/io.h11
-rw-r--r--cpu/io.s121
-rw-r--r--cpu/reload_gdt.s17
-rw-r--r--cpu/spinlock.c2
-rw-r--r--cpu/spinlock.h5
-rw-r--r--cpu/syscall.c174
-rw-r--r--cpu/syscall.h59
-rw-r--r--crypto/ChaCha20/chacha20.c29
-rw-r--r--crypto/ChaCha20/chacha20.h15
m---------crypto/SHA10
-rw-r--r--drivers/ata.c253
-rw-r--r--drivers/ata.h16
-rw-r--r--drivers/keyboard.c188
-rw-r--r--drivers/keyboard.h11
-rw-r--r--drivers/mouse.c144
-rw-r--r--drivers/mouse.h5
-rw-r--r--drivers/pit.c55
-rw-r--r--drivers/pit.h12
-rw-r--r--drivers/pst.c17
-rw-r--r--drivers/pst.h7
-rw-r--r--drivers/serial.c35
-rw-r--r--drivers/serial.h2
-rw-r--r--drivers/vbe.c50
-rw-r--r--drivers/vbe.h7
-rw-r--r--elf.c73
-rw-r--r--elf.h99
-rw-r--r--fs/devfs.c91
-rw-r--r--fs/devfs.h26
-rw-r--r--fs/ext2.c633
-rw-r--r--fs/ext2.h139
-rw-r--r--fs/fifo.c97
-rw-r--r--fs/fifo.h26
-rw-r--r--fs/shm.c98
-rw-r--r--fs/shm.h13
-rw-r--r--fs/tmpfs.c94
-rw-r--r--fs/tmpfs.h16
-rw-r--r--fs/vfs.c272
-rw-r--r--fs/vfs.h94
-rw-r--r--halts.c102
-rw-r--r--halts.h21
m---------hashmap0
-rw-r--r--includes/defs.h5
-rw-r--r--includes/mmu.h61
-rw-r--r--includes/sys/types.h2
-rw-r--r--init/kernel.c101
-rw-r--r--isodir/boot/grub/grub.cfg3
-rw-r--r--kmalloc.c233
-rw-r--r--kmalloc.h21
-rw-r--r--ksbrk.c40
-rw-r--r--ksbrk.h8
-rw-r--r--kubsan.c58
-rw-r--r--kubsan.h79
-rw-r--r--libc/exit/assert.c12
-rw-r--r--libc/include/assert.h19
-rw-r--r--libc/include/errno.h85
-rw-r--r--libc/include/limits.h1
-rw-r--r--libc/include/stdio.h9
-rw-r--r--libc/include/stdlib.h0
-rw-r--r--libc/include/string.h19
-rw-r--r--libc/include/time.h6
-rw-r--r--libc/include/types.h27
-rw-r--r--libc/stdio/print.c97
-rw-r--r--libc/string/copy.c26
-rw-r--r--libc/string/isequal.c15
-rw-r--r--libc/string/memcmp.c12
-rw-r--r--libc/string/memcpy.c11
-rw-r--r--libc/string/memset.c9
-rw-r--r--libc/string/strcat.c6
-rw-r--r--libc/string/strcmp.c8
-rw-r--r--libc/string/strcpy.c8
-rw-r--r--libc/string/strlcpy.c21
-rw-r--r--libc/string/strlen.c8
-rw-r--r--libc/string/strncpy.c11
-rw-r--r--linker.ld41
-rw-r--r--log.c40
-rw-r--r--log.h10
l---------mount/cat1
l---------mount/init1
-rwxr-xr-xmount/pid1bin0 -> 2396 bytes
-rwxr-xr-xmount/programbin0 -> 1744 bytes
-rwxr-xr-xmount/shbin0 -> 45660 bytes
-rw-r--r--multiboot.h243
-rwxr-xr-xnew.sh3
-rw-r--r--poll.c54
-rw-r--r--poll.h15
-rw-r--r--process.s33
-rw-r--r--random.c142
-rw-r--r--random.h7
-rw-r--r--read_eip.s5
-rw-r--r--scalls/accept.c5
-rw-r--r--scalls/accept.h9
-rw-r--r--scalls/bind.c5
-rw-r--r--scalls/bind.h9
-rw-r--r--scalls/clock_gettime.c10
-rw-r--r--scalls/clock_gettime.h8
-rw-r--r--scalls/mmap.c7
-rw-r--r--scalls/mmap.h13
-rw-r--r--scalls/msleep.c9
-rw-r--r--scalls/msleep.h5
-rw-r--r--scalls/ppoll.c11
-rw-r--r--scalls/ppoll.h9
-rw-r--r--scalls/shm.c10
-rw-r--r--scalls/shm.h20
-rw-r--r--scalls/socket.c5
-rw-r--r--scalls/socket.h9
-rw-r--r--scalls/stat.c13
-rw-r--r--scalls/stat.h33
-rw-r--r--scalls/uptime.c4
-rw-r--r--scalls/uptime.h2
-rw-r--r--sched/scheduler.c388
-rw-r--r--sched/scheduler.h60
-rw-r--r--socket.c148
-rw-r--r--socket.h66
-rwxr-xr-xsync.sh137
-rw-r--r--time.h10
-rw-r--r--toolchain/3A24BC1E8FB409FA9F14371813FCEF89DD9E3C4F38
-rw-r--r--toolchain/binutils-2.40.diff12573
-rwxr-xr-xtoolchain/build-binutils.sh13
-rwxr-xr-xtoolchain/build-gcc.sh13
-rwxr-xr-xtoolchain/download-binutils.sh2
-rwxr-xr-xtoolchain/download-gcc.sh2
-rwxr-xr-xtoolchain/download.sh9
-rw-r--r--toolchain/gcc-13.1.0.diff142
-rwxr-xr-xtoolchain/get-keys.sh3
-rw-r--r--userland/ante/Makefile15
-rw-r--r--userland/ante/ante.c296
-rw-r--r--userland/cat/Makefile10
-rwxr-xr-xuserland/cat/catbin0 -> 33852 bytes
-rw-r--r--userland/cat/cat.c24
-rw-r--r--userland/init/Makefile10
-rw-r--r--userland/init/crt0_old.c12
-rwxr-xr-xuserland/init/initbin0 -> 31476 bytes
-rw-r--r--userland/init/init.c15
-rw-r--r--userland/json/Makefile18
m---------userland/json/hashmap0
-rw-r--r--userland/json/json.c360
-rw-r--r--userland/json/json.h39
-rw-r--r--userland/json/libjson.abin0 -> 6304 bytes
-rw-r--r--userland/libc/Makefile26
-rw-r--r--userland/libc/arpa/inet.h4
-rw-r--r--userland/libc/arpa/inet/htonl.c11
-rw-r--r--userland/libc/arpa/inet/htons.c10
-rw-r--r--userland/libc/assert.c9
-rw-r--r--userland/libc/assert.h10
-rw-r--r--userland/libc/crt0.s13
-rw-r--r--userland/libc/ctype.h12
-rw-r--r--userland/libc/ctype/isalnum.c6
-rw-r--r--userland/libc/ctype/isalpha.c4
-rw-r--r--userland/libc/ctype/isascii.c4
-rw-r--r--userland/libc/ctype/isdigit.c6
-rw-r--r--userland/libc/ctype/isprint.c3
-rw-r--r--userland/libc/ctype/ispunct.c6
-rw-r--r--userland/libc/ctype/isxdigit.c6
-rw-r--r--userland/libc/ctype/tolower.c7
-rw-r--r--userland/libc/ctype/toupper.c7
-rw-r--r--userland/libc/dirent.h28
-rw-r--r--userland/libc/dirent/alphasort.c7
-rw-r--r--userland/libc/dirent/closedir.c7
-rw-r--r--userland/libc/dirent/opendir.c11
-rw-r--r--userland/libc/dirent/readdir.c14
-rw-r--r--userland/libc/dirent/scandir.c43
-rw-r--r--userland/libc/endian.h2
-rw-r--r--userland/libc/errno.h87
-rw-r--r--userland/libc/fcntl.h10
-rw-r--r--userland/libc/include/arpa/inet.h0
-rw-r--r--userland/libc/include/assert.h10
-rw-r--r--userland/libc/include/byteswap.h0
-rw-r--r--userland/libc/include/ctype.h14
-rw-r--r--userland/libc/include/dirent.h28
-rw-r--r--userland/libc/include/endian.h2
-rw-r--r--userland/libc/include/err.h0
-rw-r--r--userland/libc/include/errno.h87
-rw-r--r--userland/libc/include/fcntl.h12
-rw-r--r--userland/libc/include/fnmatch.h0
-rw-r--r--userland/libc/include/glob.h10
-rw-r--r--userland/libc/include/grp.h0
-rw-r--r--userland/libc/include/input.h9
-rw-r--r--userland/libc/include/inttypes.h19
-rw-r--r--userland/libc/include/langinfo.h0
-rw-r--r--userland/libc/include/libgen.h6
-rw-r--r--userland/libc/include/limits.h4
-rw-r--r--userland/libc/include/locale.h0
-rw-r--r--userland/libc/include/math.h0
-rw-r--r--userland/libc/include/net/if.h0
-rw-r--r--userland/libc/include/netdb.h0
-rw-r--r--userland/libc/include/netinet/in.h0
-rw-r--r--userland/libc/include/netinet/tcp.h0
-rw-r--r--userland/libc/include/paths.h0
-rw-r--r--userland/libc/include/poll.h17
-rw-r--r--userland/libc/include/pty.h6
-rw-r--r--userland/libc/include/pwd.h0
-rw-r--r--userland/libc/include/regex.h0
-rw-r--r--userland/libc/include/sched.h0
-rw-r--r--userland/libc/include/setjmp.h14
-rw-r--r--userland/libc/include/signal.h9
-rw-r--r--userland/libc/include/socket.h41
-rw-r--r--userland/libc/include/stdio.h116
-rw-r--r--userland/libc/include/stdlib.h32
-rw-r--r--userland/libc/include/string.h29
-rw-r--r--userland/libc/include/strings.h0
-rw-r--r--userland/libc/include/sys/ioctl.h10
-rw-r--r--userland/libc/include/sys/mman.h15
-rw-r--r--userland/libc/include/sys/mount.h0
-rw-r--r--userland/libc/include/sys/resource.h0
-rw-r--r--userland/libc/include/sys/socket.h0
-rw-r--r--userland/libc/include/sys/stat.h31
-rw-r--r--userland/libc/include/sys/statvfs.h0
-rw-r--r--userland/libc/include/sys/syscall.h0
-rw-r--r--userland/libc/include/sys/time.h41
-rw-r--r--userland/libc/include/sys/times.h0
-rw-r--r--userland/libc/include/sys/types.h28
-rw-r--r--userland/libc/include/sys/ucontext.h0
-rw-r--r--userland/libc/include/sys/un.h0
-rw-r--r--userland/libc/include/sys/utsname.h0
-rw-r--r--userland/libc/include/sys/wait.h0
-rw-r--r--userland/libc/include/syscall.h150
-rw-r--r--userland/libc/include/syslog.h0
-rw-r--r--userland/libc/include/termios.h0
-rw-r--r--userland/libc/include/time.h35
-rw-r--r--userland/libc/include/ubsan.h79
-rw-r--r--userland/libc/include/unistd.h24
-rw-r--r--userland/libc/include/utime.h0
-rw-r--r--userland/libc/include/wchar.h0
-rw-r--r--userland/libc/include/wctype.h0
-rw-r--r--userland/libc/input.h9
-rw-r--r--userland/libc/inttypes.h5
-rw-r--r--userland/libc/isspace.c5
-rw-r--r--userland/libc/libc.c287
-rw-r--r--userland/libc/libgen/basename.c45
-rw-r--r--userland/libc/libgen/dirname.c44
-rw-r--r--userland/libc/limits.h2
-rw-r--r--userland/libc/malloc/malloc.c232
-rw-r--r--userland/libc/malloc/malloc.h9
-rw-r--r--userland/libc/malloc/oldmalloc.c136
-rw-r--r--userland/libc/math.h0
-rw-r--r--userland/libc/memset.c15
-rw-r--r--userland/libc/mmap.c19
-rw-r--r--userland/libc/poll.h16
-rw-r--r--userland/libc/pty.c15
-rw-r--r--userland/libc/pty.h6
-rw-r--r--userland/libc/setjmp/longjmp.s16
-rw-r--r--userland/libc/setjmp/setjmp.s23
-rw-r--r--userland/libc/socket.h41
-rw-r--r--userland/libc/stdio.h95
-rw-r--r--userland/libc/stdio/dprintf.c9
-rw-r--r--userland/libc/stdio/fclose.c10
-rw-r--r--userland/libc/stdio/feof.c5
-rw-r--r--userland/libc/stdio/ferror.c5
-rw-r--r--userland/libc/stdio/fflush.c7
-rw-r--r--userland/libc/stdio/fgetc.c20
-rw-r--r--userland/libc/stdio/fgetpos.c7
-rw-r--r--userland/libc/stdio/fgets.c16
-rw-r--r--userland/libc/stdio/fileno.c13
-rw-r--r--userland/libc/stdio/fopen.c57
-rw-r--r--userland/libc/stdio/fprintf.c9
-rw-r--r--userland/libc/stdio/fputc.c7
-rw-r--r--userland/libc/stdio/fputs.c9
-rw-r--r--userland/libc/stdio/fread.c11
-rw-r--r--userland/libc/stdio/fscanf.c7
-rw-r--r--userland/libc/stdio/fseek.c21
-rw-r--r--userland/libc/stdio/fsetpos.c7
-rw-r--r--userland/libc/stdio/ftell.c5
-rw-r--r--userland/libc/stdio/fwrite.c12
-rw-r--r--userland/libc/stdio/getchar.c4
-rw-r--r--userland/libc/stdio/open_memstream.c108
-rw-r--r--userland/libc/stdio/printf.c9
-rw-r--r--userland/libc/stdio/putc.c3
-rw-r--r--userland/libc/stdio/putchar.c7
-rw-r--r--userland/libc/stdio/puts.c6
-rw-r--r--userland/libc/stdio/remove.c9
-rw-r--r--userland/libc/stdio/rename.c8
-rw-r--r--userland/libc/stdio/setvbuf.c6
-rw-r--r--userland/libc/stdio/snprintf.c42
-rw-r--r--userland/libc/stdio/sprintf.c33
-rw-r--r--userland/libc/stdio/stderr.c11
-rw-r--r--userland/libc/stdio/stdin.c54
-rw-r--r--userland/libc/stdio/stdout.c13
-rw-r--r--userland/libc/stdio/tmpfile.c9
-rw-r--r--userland/libc/stdio/tmpnam.c10
-rw-r--r--userland/libc/stdio/ungetc.c9
-rw-r--r--userland/libc/stdio/vdprintf.c77
-rw-r--r--userland/libc/stdio/vfprintf.c243
-rw-r--r--userland/libc/stdio/vprintf.c3
-rw-r--r--userland/libc/stdlib.h17
-rw-r--r--userland/libc/stdlib/abort.c10
-rw-r--r--userland/libc/stdlib/abs.c3
-rw-r--r--userland/libc/stdlib/atexit.c6
-rw-r--r--userland/libc/stdlib/atof.c5
-rw-r--r--userland/libc/stdlib/atoi.c4
-rw-r--r--userland/libc/stdlib/getenv.c6
-rw-r--r--userland/libc/stdlib/mkstemp.c14
-rw-r--r--userland/libc/stdlib/qsort.c29
-rw-r--r--userland/libc/stdlib/rand.c17
-rw-r--r--userland/libc/stdlib/srand.c8
-rw-r--r--userland/libc/stdlib/strtod.c70
-rw-r--r--userland/libc/stdlib/strtol.c52
-rw-r--r--userland/libc/stdlib/strtold.c9
-rw-r--r--userland/libc/stdlib/strtoul.c72
-rw-r--r--userland/libc/stdlib/system.c17
-rw-r--r--userland/libc/string.h17
-rw-r--r--userland/libc/string/memcmp.c11
-rw-r--r--userland/libc/string/memcpy.c9
-rw-r--r--userland/libc/string/memmove.c14
-rw-r--r--userland/libc/string/sscanf.c193
-rw-r--r--userland/libc/string/strcasecmp.c28
-rw-r--r--userland/libc/string/strcat.c13
-rw-r--r--userland/libc/string/strchr.c11
-rw-r--r--userland/libc/string/strcmp.c29
-rw-r--r--userland/libc/string/strcpy.c7
-rw-r--r--userland/libc/string/strcspn.c14
-rw-r--r--userland/libc/string/strdup.c15
-rw-r--r--userland/libc/string/strlcpy.c20
-rw-r--r--userland/libc/string/strlen.c8
-rw-r--r--userland/libc/string/strncasecmp.c29
-rw-r--r--userland/libc/string/strncmp.c28
-rw-r--r--userland/libc/string/strncpy.c13
-rw-r--r--userland/libc/string/strndup.c22
-rw-r--r--userland/libc/string/strnlen.c9
-rw-r--r--userland/libc/string/strpbrk.c12
-rw-r--r--userland/libc/string/strrchr.c12
-rw-r--r--userland/libc/string/strspn.c18
-rw-r--r--userland/libc/string/strstr.c21
-rw-r--r--userland/libc/string/strtok.c26
-rw-r--r--userland/libc/strings.h0
-rw-r--r--userland/libc/sys/mman.h8
-rw-r--r--userland/libc/sys/mman/mmap.c19
-rw-r--r--userland/libc/sys/stat.h30
-rw-r--r--userland/libc/sys/stat/mkdir.c9
-rw-r--r--userland/libc/sys/stat/stat.c13
-rw-r--r--userland/libc/sys/time/gettimeofday.c5
-rw-r--r--userland/libc/sys/types.h27
-rw-r--r--userland/libc/syscall.h149
-rw-r--r--userland/libc/time.h20
-rw-r--r--userland/libc/time/clock_gettime.c14
-rw-r--r--userland/libc/time/ctime_r.c13
-rw-r--r--userland/libc/time/gmtime.c21
-rw-r--r--userland/libc/time/localtime.c21
-rw-r--r--userland/libc/time/strftime.c7
-rw-r--r--userland/libc/time/time.c9
-rw-r--r--userland/libc/ubsan.c49
-rw-r--r--userland/libc/ubsan.h79
-rw-r--r--userland/libc/unistd.h14
-rw-r--r--userland/libc/unistd/_exit.c8
-rw-r--r--userland/libc/unistd/execvp.c8
-rw-r--r--userland/libc/unistd/getopt.c14
-rw-r--r--userland/libc/unistd/getpid.c7
-rw-r--r--userland/libc/unistd/msleep.c6
-rw-r--r--userland/libc/unistd/unlink.c7
-rw-r--r--userland/libc/unistd/uptime.c6
-rw-r--r--userland/libc/wchar.h0
-rw-r--r--userland/libc/wctype.h0
-rw-r--r--userland/libgui/Makefile17
-rw-r--r--userland/libgui/font.h3
-rw-r--r--userland/libgui/libgui.c290
-rw-r--r--userland/libgui/libgui.h34
-rw-r--r--userland/minibox/Makefile12
-rw-r--r--userland/minibox/minibox.c65
-rw-r--r--userland/minibox/utilities/ascii.c30
-rw-r--r--userland/minibox/utilities/cat.c54
-rw-r--r--userland/minibox/utilities/echo.c30
-rw-r--r--userland/minibox/utilities/ed.c145
-rw-r--r--userland/minibox/utilities/include.h41
-rw-r--r--userland/minibox/utilities/init.c72
-rw-r--r--userland/minibox/utilities/ls.c42
-rw-r--r--userland/minibox/utilities/minibox.c15
-rw-r--r--userland/minibox/utilities/pwd.c12
-rw-r--r--userland/minibox/utilities/touch.c11
-rw-r--r--userland/minibox/utilities/wc.c106
-rw-r--r--userland/minibox/utilities/yes.c13
-rw-r--r--userland/sh/Makefile13
-rwxr-xr-xuserland/sh/shbin0 -> 44776 bytes
-rw-r--r--userland/sh/sh.c224
-rwxr-xr-xuserland/sh/sh_abin0 -> 9200 bytes
-rwxr-xr-xuserland/sh/sh_badbin0 -> 9188 bytes
-rw-r--r--userland/snake/Makefile15
-rw-r--r--userland/snake/snake.c109
-rw-r--r--userland/terminal/Makefile15
-rw-r--r--userland/terminal/term.c166
-rw-r--r--userland/test/Makefile16
-rwxr-xr-xuserland/test/linux.sh4
-rwxr-xr-xuserland/test/local/a.outbin0 -> 35312 bytes
-rw-r--r--userland/test/local/testfile1
-rwxr-xr-xuserland/test/testbin0 -> 86144 bytes
-rw-r--r--userland/test/test.c722
-rw-r--r--userland/windowserver/Makefile16
-rw-r--r--userland/windowserver/draw.c80
-rw-r--r--userland/windowserver/draw.h13
-rw-r--r--userland/windowserver/font.h133
-rw-r--r--userland/windowserver/ws.c375
-rw-r--r--userland/windowserver/ws.h30
403 files changed, 28886 insertions, 0 deletions
diff --git a/.clang-format b/.clang-format
new file mode 100644
index 0000000..cd89955
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1 @@
+BasedOnStyle: llvm
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..82848fd
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,26 @@
+*.a
+*.o
+*.txt
+*.log
+*.bin
+*.iso
+*.img
+*.tar.xz
+*.tar.xz.sig
+.cache/
+toolchain/bin/
+toolchain/binutils-*/
+toolchain/gcc-*/
+toolchain/build-*
+userland/*
+userland/terminal/term
+!userland/libc/*
+!userland/minibox/*
+!userland/windowserver/*
+!userland/terminal/*
+!userland/libgui/*
+!userland/snake/*
+!userland/ante/*
+!userland/ante/*
+ext2.img
+mount
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..f288702
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program 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.
+
+ This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<https://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<https://www.gnu.org/licenses/why-not-lgpl.html>.
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..3b16888
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,14 @@
+Copyright (C) 2022 - 2023 Anton Kling <anton@kling.gg>
+
+This program 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.
+
+This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..74f52b4
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,33 @@
+CC="./sysroot/bin/i686-sb-gcc"
+AS="./sysroot/bin/i686-sb-as"
+OBJ = arch/i386/boot.o init/kernel.o cpu/gdt.o cpu/reload_gdt.o cpu/idt.o cpu/io.o libc/stdio/print.o drivers/keyboard.o log.o drivers/pit.o libc/string/memcpy.o libc/string/strlen.o libc/string/memcmp.o drivers/ata.o libc/string/memset.o cpu/syscall.o read_eip.o libc/exit/assert.o process.o cpu/int_syscall.o libc/string/strcpy.o arch/i386/mmu.o kmalloc.o fs/ext2.o fs/vfs.o fs/devfs.o cpu/spinlock.o random.o libc/string/strcmp.o crypto/ChaCha20/chacha20.o crypto/SHA1/sha1.o fs/tmpfs.o libc/string/isequal.o drivers/pst.o halts.o scalls/ppoll.o kubsan.o scalls/mmap.o drivers/serial.o scalls/accept.o scalls/bind.o scalls/socket.o socket.o poll.o fs/fifo.o hashmap/hashmap.o fs/shm.o scalls/shm.o elf.o ksbrk.o sched/scheduler.o scalls/stat.o libc/string/copy.o libc/string/strncpy.o drivers/mouse.o libc/string/strlcpy.o libc/string/strcat.o drivers/vbe.o scalls/msleep.o scalls/uptime.o
+CFLAGS = -O2 -fsanitize=vla-bound,shift-exponent,pointer-overflow,shift,signed-integer-overflow,bounds -ggdb -ffreestanding -Wall -Werror -mgeneral-regs-only -Wimplicit-fallthrough -I./libc/include/ -I.
+INCLUDE=-I./includes/ -I./libc/include/
+
+all: myos.iso
+
+%.o: %.c
+ $(CC) $(INCLUDE) -c -o $@ $< $(CFLAGS)
+
+%.o: %.s
+ $(AS) $< -o $@
+
+myos.bin: $(OBJ)
+ $(CC) $(INCLUDE) -shared -T linker.ld -o myos.bin -ffreestanding -nostdlib $(CFLAGS) $^ -lgcc
+
+debug:
+ qemu-system-i386 -no-reboot -no-shutdown -serial file:./serial.log -hda ext2.img -m 1G -cdrom myos.iso -s -S &
+ gdb -x .gdbinit
+
+nk:
+ qemu-system-i386 -d int -no-reboot -no-shutdown -serial file:./serial.log -hda ext2.img -m 1G -cdrom myos.iso -s
+
+run:
+ qemu-system-i386 -enable-kvm -d int -no-reboot -no-shutdown -chardev stdio,id=char0,logfile=serial.log,signal=off -serial chardev:char0 -hda ext2.img -m 1G -cdrom myos.iso -s
+
+myos.iso: myos.bin
+ cp myos.bin isodir/boot
+ grub-mkrescue -o myos.iso isodir
+
+clean:
+ rm myos.bin myos.iso $(OBJ)
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..836a31d
--- /dev/null
+++ b/README.md
@@ -0,0 +1,35 @@
+# sbOS
+
+A mostly from scratch, UNIX like x86 hobbyist operaing system. Kernel,
+libc and the rest of the userland are written from scratch. It only
+requires a bootloader that supports the first version of multiboot(such
+as GRUB).
+
+## Features
+
+* Paging
+* Interrupts
+* Process scheduling
+* VBE graphics
+* PS2 Mouse/Keyboard
+* VFS
+* ext2 filesystem
+* DevFS
+* UNIX sockets
+* libc
+* Window Manager
+* Terminal Emulator
+* Very basic shell
+* Shell utilities(cat, yes, echo etc)
+
+and some other stuff.
+
+## How do I run it?
+
+You shouldn't, it is very incomplete and does not have much intreasting
+sutff in the userland yet. Setup is currently also sligthly painful if
+you don't know what you are doing.
+
+## Why?
+
+fun
diff --git a/arch/i386/boot.s b/arch/i386/boot.s
new file mode 100644
index 0000000..61bbfbb
--- /dev/null
+++ b/arch/i386/boot.s
@@ -0,0 +1,128 @@
+.set ALIGN, 1<<0
+.set MEMINFO, 1<<1
+.set VIDEO_MODE, 1<<2
+.set FLAGS, VIDEO_MODE|ALIGN | MEMINFO
+.set MAGIC, 0x1BADB002
+.set CHECKSUM, -(MAGIC + FLAGS)
+
+#.section .multiboot
+.align 16, 0
+.section .multiboot.data, "aw"
+ .align 4
+ .long MAGIC
+ .long FLAGS
+ .long CHECKSUM
+ # unused(padding)
+ .long 0,0,0,0,0
+ # Video mode
+ .long 0 # Linear graphics
+ .long 0 # Preferred width
+ .long 0 # Preferred height
+ .long 32 # Preferred pixel depth
+
+# Allocate the initial stack.
+.section .bootstrap_stack, "aw", @nobits
+stack_bottom:
+.skip 16384 # 16 KiB
+stack_top:
+
+.global boot_page_directory
+.global boot_page_table1
+.section .bss, "aw", @nobits
+ .align 4096
+boot_page_directory:
+ .skip 4096
+boot_page_table1:
+ .skip 4096
+
+.section .multiboot.text, "a"
+.global _start
+.extern _kernel_end
+.type _start, @function
+# Kernel entry
+_start:
+ # edi contains the buffer we wish to modify
+ movl $(boot_page_table1 - 0xC0000000), %edi
+
+ # for loop
+ movl $0, %esi
+ movl $1024, %ecx
+1:
+ # esi = address
+ # If we are in kernel range jump to "label 2"
+ cmpl $_kernel_start, %esi
+ jl 2f
+
+ # If we are past the kernel jump to the final stage
+ # "label 3"
+ cmpl $(_kernel_end - 0xC0000000), %esi
+ jge 3f
+
+2:
+ # Add permission to the pages
+ movl %esi, %edx
+ orl $0x003, %edx
+ movl %edx, (%edi)
+
+ # Size of page is 4096 bytes.
+ addl $4096, %esi
+ # Size of entries in boot_page_table1 is 4 bytes.
+ addl $4, %edi
+ # Loop to the next entry if we haven't finished.
+ loop 1b
+
+3:
+ # Map the page table to both virtual addresses 0x00000000 and 0xC0000000.
+ movl $(boot_page_table1 - 0xC0000000 + 0x003), boot_page_directory - 0xC0000000 + 0
+ movl $(boot_page_table1 - 0xC0000000 + 0x003), boot_page_directory - 0xC0000000 + 768 * 4
+
+ # Set cr3 to the address of the boot_page_directory.
+ movl $(boot_page_directory - 0xC0000000), %ecx
+ movl %ecx, %cr3
+
+ # Enable paging
+ movl %cr0, %ecx
+ orl $0x80000000, %ecx
+ movl %ecx, %cr0
+
+ # Jump to higher half with an absolute jump.
+ lea 4f, %ecx
+ jmp *%ecx
+
+.size _start, . - _start
+
+.section .text
+
+4:
+ # At this point, paging is fully set up and enabled.
+
+ # Unmap the identity mapping as it is now unnecessary.
+ movl $0, boot_page_directory + 0
+
+ # Reload crc3 to force a TLB flush so the changes to take effect.
+ movl %cr3, %ecx
+ movl %ecx, %cr3
+
+ # Set up the stack.
+ mov $stack_top, %esp
+
+ # Reset EFLAGS.
+ pushl $0
+ popf
+
+ pushl %esp
+
+ /* Push the pointer to the Multiboot information structure. */
+ pushl %ebx
+ /* Push the magic value. */
+ pushl %eax
+
+ mov $_kernel_end, %eax
+ pushl %eax
+ # Enter the high-level kernel.
+ call kernel_main
+
+ # Infinite loop if the system has nothing more to do.
+ cli
+1: hlt
+ jmp 1b
diff --git a/arch/i386/mmu.c b/arch/i386/mmu.c
new file mode 100644
index 0000000..6fff8f2
--- /dev/null
+++ b/arch/i386/mmu.c
@@ -0,0 +1,565 @@
+#include <assert.h>
+#include <ksbrk.h>
+#include <log.h>
+#include <mmu.h>
+
+#define INDEX_FROM_BIT(a) (a / (32))
+#define OFFSET_FROM_BIT(a) (a % (32))
+#define PAGE_SIZE ((uintptr_t)0x1000)
+
+#define PAGE_ALLOCATE 1
+#define PAGE_NO_ALLOCATE 0
+
+PageDirectory *kernel_directory;
+PageDirectory real_kernel_directory;
+PageDirectory *active_directory = 0;
+
+#define END_OF_MEMORY 0x8000000 * 15
+const uint32_t num_of_frames = END_OF_MEMORY / PAGE_SIZE;
+uint32_t frames[END_OF_MEMORY / PAGE_SIZE] = {0};
+uint32_t num_allocated_frames = 0;
+
+#define KERNEL_START 0xc0000000
+extern uintptr_t data_end;
+
+void write_to_frame(uint32_t frame_address, uint8_t on);
+
+void *ksbrk(size_t s) {
+ uintptr_t rc = (uintptr_t)align_page((void *)data_end);
+ data_end += s;
+ data_end = (uintptr_t)align_page((void *)data_end);
+
+ if (!get_active_pagedirectory()) {
+ // If there is no active pagedirectory we
+ // just assume that the memory is
+ // already mapped.
+ return (void *)rc;
+ }
+ // Determine whether we are approaching a unallocated table
+ int table_index = 1 + (rc / (1024 * 0x1000));
+ if (!active_directory->tables[table_index]) {
+ uint32_t physical;
+ active_directory->tables[table_index] = (PageTable *)0xDEADBEEF;
+ active_directory->tables[table_index] =
+ (PageTable *)ksbrk_physical(sizeof(PageTable), (void **)&physical);
+ memset(active_directory->tables[table_index], 0, sizeof(PageTable));
+ active_directory->physical_tables[table_index] = (uint32_t)physical | 0x3;
+
+ kernel_directory->tables[table_index] =
+ active_directory->tables[table_index];
+ kernel_directory->physical_tables[table_index] =
+ active_directory->physical_tables[table_index];
+ return ksbrk(s);
+ }
+ mmu_allocate_shared_kernel_region((void *)rc, (data_end - (uintptr_t)rc));
+ assert(((uintptr_t)rc % PAGE_SIZE) == 0);
+ memset((void *)rc, 0x00, s);
+
+ return (void *)rc;
+}
+
+void *ksbrk_physical(size_t s, void **physical) {
+ void *r = ksbrk(s);
+ if (physical) {
+ *physical = (void *)virtual_to_physical(r, 0);
+ }
+ return r;
+}
+
+uint32_t mmu_get_number_of_allocated_frames(void) {
+ return num_allocated_frames;
+}
+
+Page *get_page(void *ptr, PageDirectory *directory, int create_new_page,
+ int set_user) {
+ uintptr_t address = (uintptr_t)ptr;
+ if (!directory)
+ directory = get_active_pagedirectory();
+ address /= 0x1000;
+
+ uint32_t table_index = address / 1024;
+ if (!directory->tables[table_index]) {
+ if (!create_new_page)
+ return 0;
+
+ uint32_t physical;
+ directory->tables[table_index] =
+ (PageTable *)ksbrk_physical(sizeof(PageTable), (void **)&physical);
+ memset(directory->tables[table_index], 0, sizeof(PageTable));
+ directory->physical_tables[table_index] =
+ (uint32_t)physical | ((set_user) ? 0x7 : 0x3);
+
+ if (!set_user) {
+ kernel_directory->tables[table_index] = directory->tables[table_index];
+ kernel_directory->physical_tables[table_index] =
+ directory->physical_tables[table_index];
+ }
+ }
+ Page *p = &directory->tables[table_index]->pages[address % 1024];
+ if (create_new_page) {
+ p->present = 0;
+ }
+ return &directory->tables[table_index]->pages[address % 1024];
+}
+
+void mmu_free_pages(void *a, uint32_t n) {
+ for (; n > 0; n--) {
+ Page *p = get_page(a, NULL, PAGE_NO_ALLOCATE, 0);
+ p->present = 0;
+ write_to_frame(p->frame * 0x1000, 0);
+ a += 0x1000;
+ }
+}
+
+void *next_page(void *ptr) {
+ uintptr_t a = (uintptr_t)ptr;
+ return (void *)(a + (PAGE_SIZE - ((uint32_t)a & (PAGE_SIZE - 1))));
+}
+
+void *align_page(void *a) {
+ if ((uintptr_t)a & (PAGE_SIZE - 1))
+ return next_page(a);
+
+ return a;
+}
+
+void flush_tlb(void) {
+ asm volatile("\
+ mov %cr3, %eax;\
+ mov %eax, %cr3");
+}
+
+uint32_t first_free_frame(void) {
+ asm("cli");
+ for (uint32_t i = 1; i < INDEX_FROM_BIT(num_of_frames); i++) {
+ if (frames[i] == 0xFFFFFFFF)
+ continue;
+
+ for (uint32_t c = 0; c < 32; c++)
+ if (!(frames[i] & ((uint32_t)1 << c)))
+ return i * 32 + c;
+ }
+
+ kprintf("ERROR Num frames: %x\n", mmu_get_number_of_allocated_frames());
+ klog("No free frames, uh oh.", LOG_ERROR);
+ assert(0);
+ return 0;
+}
+
+void write_to_frame(uint32_t frame_address, uint8_t on) {
+ uint32_t frame = frame_address / 0x1000;
+ assert(INDEX_FROM_BIT(frame) < sizeof(frames) / sizeof(frames[0]));
+ if (on) {
+ num_allocated_frames++;
+ frames[INDEX_FROM_BIT(frame)] |= ((uint32_t)0x1 << OFFSET_FROM_BIT(frame));
+ return;
+ }
+ num_allocated_frames--;
+ frames[INDEX_FROM_BIT(frame)] &= ~((uint32_t)0x1 << OFFSET_FROM_BIT(frame));
+}
+
+PageDirectory *get_active_pagedirectory(void) { return active_directory; }
+
+PageTable *clone_table(uint32_t src_index, PageDirectory *src_directory,
+ uint32_t *physical_address) {
+ PageTable *new_table =
+ ksbrk_physical(sizeof(PageTable), (void **)physical_address);
+ PageTable *src = src_directory->tables[src_index];
+
+ // Copy all the pages
+ for (uint16_t i = 0; i < 1024; i++) {
+ if (!src->pages[i].present) {
+ new_table->pages[i].present = 0;
+ continue;
+ }
+ uint32_t frame_address = first_free_frame();
+ write_to_frame(frame_address * 0x1000, 1);
+ new_table->pages[i].frame = frame_address;
+
+ new_table->pages[i].present |= src->pages[i].present;
+ new_table->pages[i].rw |= src->pages[i].rw;
+ new_table->pages[i].user |= src->pages[i].user;
+ new_table->pages[i].accessed |= src->pages[i].accessed;
+ new_table->pages[i].dirty |= src->pages[i].dirty;
+ }
+
+ // Now copy all of the data to the new table. This is done by creating a
+ // virutal pointer to this newly created tables physical frame so we can
+ // copy data to it.
+ for (uint32_t i = 0; i < 1024; i++) {
+ // Find a unused table
+ if (src_directory->tables[i])
+ continue;
+
+ // Link the table to the new table temporarily
+ src_directory->tables[i] = new_table;
+ src_directory->physical_tables[i] = *physical_address | 0x7;
+ PageDirectory *tmp = get_active_pagedirectory();
+ switch_page_directory(src_directory);
+
+ // For each page in the table copy all the data over.
+ for (uint32_t c = 0; c < 1024; c++) {
+ // Only copy pages that are used.
+ if (!src->pages[c].frame || !src->pages[c].present)
+ continue;
+
+ uint32_t table_data_pointer = i << 22 | c << 12;
+ uint32_t src_data_pointer = src_index << 22 | c << 12;
+ memcpy((void *)table_data_pointer, (void *)src_data_pointer, 0x1000);
+ }
+ src_directory->tables[i] = 0;
+ src_directory->physical_tables[i] = 0;
+ switch_page_directory(tmp);
+ return new_table;
+ }
+ ASSERT_NOT_REACHED;
+ return 0;
+}
+
+PageTable *copy_table(PageTable *src, uint32_t *physical_address) {
+ PageTable *new_table =
+ ksbrk_physical(sizeof(PageTable), (void **)physical_address);
+
+ // copy all the pages
+ for (uint16_t i = 0; i < 1024; i++) {
+ if (!src->pages[i].present) {
+ new_table->pages[i].present = 0;
+ continue;
+ }
+ new_table->pages[i].frame = src->pages[i].frame;
+ new_table->pages[i].present = src->pages[i].present;
+ new_table->pages[i].rw = src->pages[i].rw;
+ new_table->pages[i].user = src->pages[i].user;
+ new_table->pages[i].accessed = src->pages[i].accessed;
+ new_table->pages[i].dirty = src->pages[i].dirty;
+ }
+ return new_table;
+}
+
+PageDirectory *clone_directory(PageDirectory *original) {
+ if (!original)
+ original = get_active_pagedirectory();
+
+ uint32_t physical_address;
+ PageDirectory *new_directory =
+ ksbrk_physical(sizeof(PageDirectory), (void **)&physical_address);
+ uint32_t offset =
+ (uint32_t)new_directory->physical_tables - (uint32_t)new_directory;
+ new_directory->physical_address = physical_address + offset;
+
+ for (int i = 0; i < 1024; i++) {
+ if (!original->tables[i]) {
+ new_directory->tables[i] = NULL;
+ new_directory->physical_tables[i] = (uint32_t)NULL;
+ continue;
+ }
+
+ // Make sure to copy instead of cloning the stack.
+ if (i >= 635 && i <= 641) {
+ uint32_t physical;
+ new_directory->tables[i] = clone_table(i, original, &physical);
+ new_directory->physical_tables[i] =
+ physical | (original->physical_tables[i] & 0xFFF);
+ continue;
+ }
+
+ // if (original->tables[i] == kernel_directory->tables[i]) {
+ if (i > 641) {
+ new_directory->tables[i] = kernel_directory->tables[i];
+ new_directory->physical_tables[i] = kernel_directory->physical_tables[i];
+ continue;
+ }
+
+ uint32_t physical;
+ new_directory->tables[i] = clone_table(i, original, &physical);
+ new_directory->physical_tables[i] =
+ physical | (original->physical_tables[i] & 0xFFF);
+ }
+
+ return new_directory;
+}
+
+void mmu_allocate_shared_kernel_region(void *rc, size_t n) {
+ size_t num_pages = n / PAGE_SIZE;
+ for (size_t i = 0; i <= num_pages; i++) {
+ Page *p = get_page((void *)(rc + i * 0x1000), NULL, PAGE_NO_ALLOCATE, 0);
+ if (!p) {
+ kprintf("don't have: %x\n", rc + i * 0x1000);
+ p = get_page((void *)(rc + i * 0x1000), NULL, PAGE_ALLOCATE, 0);
+ }
+ if (!p->present || !p->frame)
+ allocate_frame(p, 0, 1);
+ }
+}
+
+void mmu_remove_virtual_physical_address_mapping(void *ptr, size_t length) {
+ size_t num_pages = (uintptr_t)align_page((void *)length) / PAGE_SIZE;
+ for (size_t i = 0; i < num_pages; i++) {
+ Page *p = get_page(ptr + (i * PAGE_SIZE), NULL, PAGE_NO_ALLOCATE, 0);
+ if (!p)
+ return;
+ p->frame = 0;
+ p->present = 0;
+ }
+}
+
+void *mmu_find_unallocated_virtual_range(void *addr, size_t length) {
+ addr = align_page(addr);
+ // Check if the pages already exist
+ for (size_t i = 0; i < length; i += 0x1000) {
+ if (get_page(addr + i, NULL, PAGE_NO_ALLOCATE, 0)) {
+ // Page already exists
+ return mmu_find_unallocated_virtual_range(addr + 0x1000, length);
+ }
+ }
+ return addr;
+}
+
+int mmu_allocate_region(void *ptr, size_t n, mmu_flags flags) {
+ size_t num_pages = n / 0x1000;
+ for (size_t i = 0; i <= num_pages; i++) {
+ Page *p = get_page((void *)(ptr + i * 0x1000), get_active_pagedirectory(),
+ PAGE_ALLOCATE, 1);
+ assert(p);
+ int rw = (flags & MMU_FLAG_RW);
+ int kernel = (flags & MMU_FLAG_KERNEL);
+ if (!allocate_frame(p, rw, kernel)) {
+ klog("MMU: Frame allocation failed", LOG_WARN);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+void *mmu_map_frames(void *const ptr, size_t s) {
+ void *const r = mmu_find_unallocated_virtual_range((void *)0xEF000000, s);
+ kprintf("r: %x\n", r);
+ size_t num_pages = s / 0x1000;
+ for (size_t i = 0; i <= num_pages; i++) {
+ Page *p = get_page((void *)(r + i * 0x1000), NULL, PAGE_ALLOCATE, 1);
+ assert(p);
+ int rw = 1;
+ int is_kernel = 1;
+ p->present = 1;
+ p->rw = rw;
+ p->user = !is_kernel;
+ p->frame = (uintptr_t)(ptr + i * 0x1000) / 0x1000;
+ write_to_frame((uintptr_t)ptr + i * 0x1000, 1);
+ }
+ flush_tlb();
+ return r;
+}
+
+void *allocate_frame(Page *page, int rw, int is_kernel) {
+ if (page->present) {
+ dump_backtrace(5);
+ klog("Page is already set", 1);
+ for (;;)
+ ;
+ return 0;
+ }
+ uint32_t frame_address = first_free_frame();
+ assert(frame_address < sizeof(frames) / sizeof(frames[0]));
+ write_to_frame(frame_address * 0x1000, 1);
+
+ page->present = 1;
+ page->rw = rw;
+ page->user = !is_kernel;
+ page->frame = frame_address;
+ return (void *)(frame_address * 0x1000);
+}
+
+void mmu_free_address_range(void *ptr, size_t length) {
+ size_t num_pages = (size_t)align_page((void *)length) / PAGE_SIZE;
+ for (size_t i = 0; i < num_pages; i++, ptr += PAGE_SIZE) {
+ Page *page = get_page(ptr, NULL, PAGE_NO_ALLOCATE, 0);
+ if (!page)
+ continue;
+ if (!page->present)
+ continue;
+ if (!page->frame)
+ continue;
+ // Sanity check that none of the frames are invalid
+ assert(page->frame < sizeof(frames) / sizeof(frames[0]));
+ write_to_frame(((uint32_t)page->frame) * 0x1000, 0);
+ page->present = 0;
+ page->rw = 0;
+ page->user = 0;
+ page->frame = 0;
+ }
+}
+
+void mmu_map_directories(void *dst, PageDirectory *d, void *src,
+ PageDirectory *s, size_t length) {
+ d = (!d) ? get_active_pagedirectory() : d;
+ s = (!s) ? get_active_pagedirectory() : s;
+ size_t num_pages = (uint32_t)align_page((void *)length) / 0x1000;
+ for (size_t i = 0; i < num_pages; i++, dst += 0x1000, src += 0x1000) {
+ Page *p = get_page(dst, d, PAGE_ALLOCATE, 1);
+ p->present = 1;
+ p->rw = 1;
+ p->user = 1;
+ void *physical = virtual_to_physical(src, s);
+ p->frame = (uint32_t)physical / PAGE_SIZE;
+ }
+ flush_tlb();
+}
+
+void mmu_map_physical(void *dst, PageDirectory *d, void *physical,
+ size_t length) {
+ d = (!d) ? get_active_pagedirectory() : d;
+ size_t num_pages = (uint32_t)align_page((void *)length) / 0x1000;
+ for (size_t i = 0; i < num_pages; i++, dst += 0x1000, physical += 0x1000) {
+ Page *p = get_page(dst, d, PAGE_ALLOCATE, 1);
+ p->present = 1;
+ p->rw = 1;
+ p->user = 1;
+ p->frame = (uintptr_t)physical / PAGE_SIZE;
+ write_to_frame((uintptr_t)physical, 1);
+ }
+ flush_tlb();
+}
+
+void *virtual_to_physical(void *address, PageDirectory *directory) {
+ if (0 == directory)
+ directory = get_active_pagedirectory();
+ return (void *)((get_page((void *)address, directory, PAGE_NO_ALLOCATE, 0)
+ ->frame *
+ 0x1000) +
+ (((uintptr_t)address) & 0xFFF));
+}
+
+extern uint32_t inital_esp;
+void __attribute__((optimize("O0")))
+move_stack(uint32_t new_stack_address, uint32_t size) {
+ mmu_allocate_region((void *)(new_stack_address - size), size,
+ MMU_FLAG_KERNEL);
+
+ uint32_t old_stack_pointer, old_base_pointer;
+
+ register uint32_t eax asm("eax");
+ asm volatile("mov %esp, %eax");
+ old_stack_pointer = eax;
+ asm volatile("mov %ebp, %eax");
+ old_base_pointer = eax;
+
+ uint32_t new_stack_pointer =
+ old_stack_pointer + ((uint32_t)new_stack_address - inital_esp);
+ uint32_t new_base_pointer =
+ old_base_pointer + ((uint32_t)new_stack_address - inital_esp);
+
+ // Copy the stack
+ memcpy((void *)new_stack_pointer, (void *)old_stack_pointer,
+ inital_esp - old_stack_pointer);
+ for (uint32_t i = (uint32_t)new_stack_address; i > new_stack_address - size;
+ i -= 4) {
+ uint32_t tmp = *(uint32_t *)i;
+ if (old_stack_pointer < tmp && tmp < inital_esp) {
+ tmp = tmp + (new_stack_address - inital_esp);
+ uint32_t *tmp2 = (uint32_t *)i;
+ *tmp2 = tmp;
+ }
+ }
+
+ inital_esp = new_stack_pointer;
+ // Actually change the stack
+ eax = new_stack_pointer;
+ asm volatile("mov %eax, %esp");
+ eax = new_base_pointer;
+ asm volatile("mov %eax, %ebp");
+}
+
+// C strings have a unknown length so it does not makes sense to check
+// for a size on the pointer. Instead we check whether the page it
+// resides in is accessible to the user.
+void *is_valid_user_c_string(const char *ptr, size_t *size) {
+ void *r = (void *)ptr;
+ size_t s = 0;
+ for (;;) {
+ void *page = (void *)((uintptr_t)ptr & (uintptr_t)(~(PAGE_SIZE - 1)));
+ if (!is_valid_userpointer(page, PAGE_SIZE))
+ return NULL;
+ for (; (uintptr_t)ptr & (PAGE_SIZE - 1); ptr++, s++)
+ if (!*ptr) {
+ if (size)
+ *size = s;
+ return r;
+ }
+ }
+}
+
+void *is_valid_userpointer(const void *ptr, size_t s) {
+ uintptr_t t = (uintptr_t)ptr;
+ size_t num_pages = (uintptr_t)align_page((void *)s) / 0x1000;
+ for (size_t i = 0; i < num_pages; i++, t += 0x1000) {
+ Page *page = get_page((void *)t, NULL, PAGE_NO_ALLOCATE, 0);
+ if (!page)
+ return NULL;
+ if (!page->present)
+ return NULL;
+ if (!page->user)
+ return NULL;
+ }
+ return (void *)ptr;
+}
+
+void switch_page_directory(PageDirectory *directory) {
+ active_directory = directory;
+ asm("mov %0, %%cr3" ::"r"(directory->physical_address));
+}
+
+void enable_paging(void) {
+ asm("mov %cr0, %eax\n"
+ "or 0b10000000000000000000000000000000, %eax\n"
+ "mov %eax, %cr0\n");
+}
+
+extern uint32_t boot_page_directory;
+extern uint32_t boot_page_table1;
+
+void paging_init(void) {
+ uint32_t *cr3;
+ asm volatile("mov %%cr3, %0" : "=r"(cr3));
+ uint32_t *virtual = (uint32_t *)((uint32_t)cr3 + 0xC0000000);
+
+ kernel_directory = &real_kernel_directory;
+ kernel_directory->physical_address = (uint32_t)cr3;
+ for (uint32_t i = 0; i < 1024; i++) {
+ kernel_directory->physical_tables[i] = virtual[i];
+
+ if (!kernel_directory->physical_tables[i]) {
+ kernel_directory->tables[i] = NULL;
+ continue;
+ }
+
+ kernel_directory->tables[i] =
+ (PageTable *)(0xC0000000 + (virtual[i] & ~(0xFFF)));
+
+ // Loop through the pages in the table
+ PageTable *table = kernel_directory->tables[i];
+ for (size_t j = 0; j < 1024; j++) {
+ if (!table->pages[j].present)
+ continue;
+ // Add the frame to our bitmap to ensure it does not get used by
+ // another newly created page.
+ write_to_frame(table->pages[j].frame * 0x1000, 1);
+ }
+ }
+
+ switch_page_directory(kernel_directory);
+ kernel_directory = clone_directory(kernel_directory);
+
+ // Make null dereferences crash.
+ switch_page_directory(kernel_directory);
+ get_page(NULL, kernel_directory, PAGE_ALLOCATE, 0)->present = 0;
+ switch_page_directory(clone_directory(kernel_directory));
+ // FIXME: Really hacky solution. Since page table creation needs to
+ // allocate memory but memory allocation requires page table creation
+ // they depend on eachother. The bad/current solution is just to
+ // allocate a bunch of tables so the memory allocator has enough.
+ for (uintptr_t i = 0; i < 140; i++)
+ allocate_frame(
+ get_page((void *)((0x302 + i) * 0x1000 * 1024), NULL, PAGE_ALLOCATE, 0),
+ 1, 1);
+ move_stack(0xA0000000, 0xC00000);
+}
diff --git a/cpu/gdt.c b/cpu/gdt.c
new file mode 100644
index 0000000..28853cf
--- /dev/null
+++ b/cpu/gdt.c
@@ -0,0 +1,72 @@
+#include "gdt.h"
+
+extern void flush_tss(void);
+extern void load_gdt(void *);
+
+typedef struct tss_entry_struct tss_entry_t;
+
+tss_entry_t tss_entry;
+
+typedef union {
+ struct GDT_Entry s;
+ uint64_t raw;
+} GDT_Entry;
+
+GDT_Entry gdt_entries[6] = {0};
+GDT_Pointer gdtr;
+
+extern uint32_t inital_esp;
+void write_tss(struct GDT_Entry *gdt_entry) {
+ uint32_t base = (uint32_t)&tss_entry;
+ uint32_t limit = sizeof(tss_entry);
+
+ gdt_entry->limit_low = limit;
+ gdt_entry->base_low = base;
+ gdt_entry->accessed = 1;
+ gdt_entry->read_write = 0;
+ gdt_entry->conforming_expand_down = 0;
+ gdt_entry->code = 1;
+ gdt_entry->code_data_segment = 0;
+ gdt_entry->DPL = 0;
+ gdt_entry->present = 1;
+ gdt_entry->limit_high = limit >> 16;
+ gdt_entry->available = 0;
+ gdt_entry->long_mode = 0;
+ gdt_entry->big = 0;
+ gdt_entry->gran = 0;
+ gdt_entry->base_high = (base & ((uint32_t)0xff << 24)) >> 24;
+
+ memset(&tss_entry, 0, sizeof tss_entry);
+ tss_entry.ss0 = GDT_KERNEL_DATA_SEGMENT * GDT_ENTRY_SIZE;
+ register uint32_t esp asm("esp");
+ tss_entry.esp0 = esp;
+}
+
+void gdt_init() {
+ gdt_entries[GDT_NULL_SEGMENT].raw = 0x0;
+ gdt_entries[GDT_KERNEL_CODE_SEGMENT].raw =
+ 0xCF9A000000FFFF; // Kernel code segment
+ gdt_entries[GDT_KERNEL_DATA_SEGMENT].raw =
+ 0xCF92000000FFFF; // Kernel data segment
+
+ // Usermode code segment
+ memcpy(&gdt_entries[GDT_USERMODE_CODE_SEGMENT],
+ &gdt_entries[GDT_KERNEL_CODE_SEGMENT], GDT_ENTRY_SIZE);
+
+ // Usermode data segment
+ memcpy(&gdt_entries[GDT_USERMODE_DATA_SEGMENT],
+ &gdt_entries[GDT_KERNEL_DATA_SEGMENT], GDT_ENTRY_SIZE);
+
+ // Set DPL to 3 to indicate that the segment is in ring 3
+ gdt_entries[GDT_USERMODE_CODE_SEGMENT].s.DPL = 3;
+ gdt_entries[GDT_USERMODE_DATA_SEGMENT].s.DPL = 3;
+
+ write_tss((struct GDT_Entry *)&gdt_entries[GDT_TSS_SEGMENT]);
+
+ gdtr.offset = (uint32_t)&gdt_entries;
+ gdtr.size = sizeof(gdt_entries) - 1;
+
+ asm("cli");
+ load_gdt(&gdtr);
+ flush_tss();
+}
diff --git a/cpu/gdt.h b/cpu/gdt.h
new file mode 100644
index 0000000..a490dea
--- /dev/null
+++ b/cpu/gdt.h
@@ -0,0 +1,76 @@
+#ifndef GDT_H
+#define GDT_H
+#include <stdint.h>
+#include <string.h>
+
+#define GDT_ENTRY_SIZE 0x8
+#define GDT_NULL_SEGMENT 0x0
+#define GDT_KERNEL_CODE_SEGMENT 0x1
+#define GDT_KERNEL_DATA_SEGMENT 0x2
+#define GDT_USERMODE_CODE_SEGMENT 0x3
+#define GDT_USERMODE_DATA_SEGMENT 0x4
+#define GDT_TSS_SEGMENT 0x5
+
+struct GDT_Entry
+{
+ uint16_t limit_low;
+ uint32_t base_low : 24;
+ uint32_t accessed : 1;
+ uint32_t read_write : 1; // readable for code, writable for data
+ uint32_t conforming_expand_down : 1; // conforming for code, expand down for data
+ uint32_t code : 1; // 1 for code, 0 for data
+ uint32_t code_data_segment : 1; // should be 1 for everything but TSS and LDT
+ uint32_t DPL : 2; // privilege level
+ uint32_t present : 1;
+ uint32_t limit_high : 4;
+ uint32_t available : 1; // only used in software; has no effect on hardware
+ uint32_t long_mode : 1;
+ uint32_t big : 1; // 32-bit opcodes for code, uint32_t stack for data
+ uint32_t gran : 1; // 1 to use 4k page addressing, 0 for byte addressing
+ uint8_t base_high;
+}__attribute__((packed));
+
+typedef struct GDT_Pointer
+{
+ uint16_t size;
+ uint32_t offset;
+}__attribute__((packed)) GDT_Pointer;
+
+struct tss_entry_struct
+{
+ uint32_t prev_tss; // The previous TSS - with hardware task switching these form a kind of backward linked list.
+ uint32_t esp0; // The stack pointer to load when changing to kernel mode.
+ uint32_t ss0; // The stack segment to load when changing to kernel mode.
+ // Everything below here is unused.
+ uint32_t esp1; // esp and ss 1 and 2 would be used when switching to rings 1 or 2.
+ uint32_t ss1;
+ uint32_t esp2;
+ uint32_t ss2;
+ uint32_t cr3;
+ uint32_t eip;
+ uint32_t eflags;
+ uint32_t eax;
+ uint32_t ecx;
+ uint32_t edx;
+ uint32_t ebx;
+ uint32_t esp;
+ uint32_t ebp;
+ uint32_t esi;
+ uint32_t edi;
+ uint32_t es;
+ uint32_t cs;
+ uint32_t ss;
+ uint32_t ds;
+ uint32_t fs;
+ uint32_t gs;
+ uint32_t ldt;
+ uint16_t trap;
+ uint16_t iomap_base;
+} __attribute__((packed));
+
+void gdt_init();
+
+uint8_t gen_access_byte(uint8_t priv, uint8_t s, uint8_t ex, uint8_t dc, uint8_t rw);
+uint64_t gen_gdt_entry(uint32_t base, uint32_t limit, uint8_t access_byte, uint8_t flag);
+uint8_t gen_flag(uint8_t gr, uint8_t sz);
+#endif
diff --git a/cpu/idt.c b/cpu/idt.c
new file mode 100644
index 0000000..832162c
--- /dev/null
+++ b/cpu/idt.c
@@ -0,0 +1,265 @@
+#include <cpu/idt.h>
+#include <sched/scheduler.h>
+#include <stdio.h>
+
+#define MASTER_PIC_COMMAND_PORT 0x20
+#define MASTER_PIC_DATA_PORT 0x21
+#define SLAVE_PIC_COMMAND_PORT 0xA0
+#define SLAVE_PIC_DATA_PORT 0xA1
+#define KEYBOARD_DATA_PORT 0x60
+#define KEYBOARD_STATUS_PORT 0x64
+#define KERNEL_CODE_SEGMENT_OFFSET GDT_ENTRY_SIZE *GDT_KERNEL_CODE_SEGMENT
+
+#define IDT_MAX_ENTRY 256
+
+struct IDT_Descriptor {
+ uint16_t low_offset;
+ uint16_t code_segment_selector;
+ uint8_t zero; // Always should be zero
+ uint8_t type_attribute;
+ uint16_t high_offset;
+} __attribute__((packed)) __attribute__((aligned(4)));
+
+struct IDT_Pointer {
+ uint16_t size;
+ struct IDT_Descriptor **interrupt_table;
+} __attribute__((packed));
+
+struct IDT_Descriptor IDT_Entry[IDT_MAX_ENTRY];
+struct IDT_Pointer idtr;
+
+extern void load_idtr(void *idtr);
+
+void format_descriptor(uint32_t offset, uint16_t code_segment,
+ uint8_t type_attribute,
+ struct IDT_Descriptor *descriptor) {
+ descriptor->low_offset = offset & 0xFFFF;
+ descriptor->high_offset = offset >> 16;
+ descriptor->type_attribute = type_attribute;
+ descriptor->code_segment_selector = code_segment;
+ descriptor->zero = 0;
+}
+
+void install_handler(void (*handler_function)(), uint16_t type_attribute,
+ uint8_t entry) {
+ format_descriptor((uint32_t)handler_function, KERNEL_CODE_SEGMENT_OFFSET,
+ type_attribute, &IDT_Entry[entry]);
+}
+
+__attribute__((no_caller_saved_registers)) void EOI(uint8_t irq) {
+ if (irq > 7)
+ outb(SLAVE_PIC_COMMAND_PORT, 0x20);
+
+ outb(MASTER_PIC_COMMAND_PORT, 0x20);
+}
+
+__attribute__((interrupt)) void
+kernel_general_protection_fault(kernel_registers_t *regs) {
+ asm("cli");
+ klog("General Protetion Fault", 0x1);
+ kprintf(" Error Code: %x\n", regs->error_code);
+ kprintf("Instruction Pointer: %x\n", regs->eip);
+ dump_backtrace(12);
+ for (;;)
+ ;
+ EOI(0xD - 8);
+}
+
+__attribute__((interrupt)) void general_protection_fault(registers_t *regs) {
+ kprintf("\n");
+ klog("KERNEL General Protetion Fault", 0x1);
+ kprintf(" Error Code: %x\n", regs->error_code);
+#define EXTERNAL_TO_PROCESSOR (1 << 0)
+
+#define WAS(_b) if (regs->error_code & (_b))
+ if (0 == regs->error_code) {
+ kprintf("This exception is not segment related.");
+ } else {
+ WAS(EXTERNAL_TO_PROCESSOR) {
+ kprintf("Exception originated externally to the processor.");
+ }
+ kprintf("Index references: ");
+ switch ((regs->error_code >> 1) & 0x3) {
+ case 0:
+ kprintf("GDT");
+ break;
+ case 3:
+ case 1:
+ kprintf("IDT");
+ break;
+ case 2:
+ kprintf("LDT");
+ break;
+ }
+ kprintf("\n");
+ kprintf("Segmenet index: %x\n", regs->error_code >> 15);
+ }
+ /* kprintf(" Page protection violation: %x\n", regs->error_code & 0x1);
+ kprintf(" Write access: %x\n", (regs->error_code & (0x1<<1)) >> 1);
+ kprintf(" No privilege violation: %x\n", (regs->error_code & (0x1<<2))
+ >> 2); kprintf(" Instruction fetch: %x\n", (regs->error_code & (0x1<<4)) >>
+ 4); kprintf(" Shadow stack access: %x\n", (regs->error_code & (0x1<<6)) >>
+ 6);*/
+ kprintf("Instruction Pointer: %x\n", regs->eip);
+ asm("hlt");
+ EOI(0xD - 8);
+}
+
+__attribute__((interrupt)) void double_fault(registers_t *regs) {
+ (void)regs;
+ klog("DOUBLE FAULT, THIS IS REALLY BAD", LOG_ERROR);
+ asm("hlt");
+ for (;;)
+ ;
+}
+__attribute__((interrupt)) void page_fault(registers_t *regs) {
+ asm("cli");
+ klog("Page Fault", LOG_ERROR);
+ if (get_current_task()) {
+ kprintf(" PID: %x\n", get_current_task()->pid);
+ kprintf(" Name: %s\n", get_current_task()->program_name);
+ }
+ kprintf(" Error Code: %x\n", regs->error_code);
+ kprintf(" Interrupt Number: %x\n", regs->interrupt_number);
+ kprintf(" Instruction Pointer: %x\n", regs->eip);
+ dump_backtrace(14);
+ asm("hlt");
+ for (;;)
+ ;
+}
+
+/*
+__attribute__((interrupt)) void page_fault(registers_t *regs) {
+ asm("cli");
+ klog("Page Fault", LOG_ERROR);
+ if (get_current_task()) {
+ kprintf(" PID: %x\n", get_current_task()->pid);
+ kprintf(" Name: %s\n", get_current_task()->program_name);
+ }
+ kprintf(" Error Code: %x\n", regs->error_code);
+ kprintf(" Interrupt Number: %x\n", regs->interrupt_number);
+#define PAGE_PRESENT (1 << 0)
+#define WRITE_ATTEMPT (1 << 1)
+#define USER_LEVEL (1 << 2)
+#define RESERVED_WRITE (1 << 3)
+#define INSTRUCTION_FETCH (1 << 4)
+#define PROTECTION_KEY_VIOLATION (1 << 5)
+#define SHADOW_STACK_ACCESS (1 << 6)
+
+#define WAS(_b) if (regs->error_code & (_b))
+
+ WAS(PAGE_PRESENT) { kprintf(" Page was present.\n"); }
+ else {
+ kprintf(" Page is not present.\n");
+ }
+
+ WAS(WRITE_ATTEMPT) { kprintf(" Write attempt.\n"); }
+ else {
+ kprintf(" Read attempt.\n");
+ }
+
+ WAS(USER_LEVEL) {
+ get_current_task()->dead = 1;
+ kprintf(" Page fault in ring 3.\n");
+ }
+ else {
+ kprintf(" Page fault in ring 0-2.\n");
+ }
+
+ WAS(INSTRUCTION_FETCH) { kprintf(" Attempted instruction fetch.\n"); }
+
+ WAS(SHADOW_STACK_ACCESS) { kprintf(" Attempted shadow stack access.\n"); }
+
+ kprintf(" Instruction Pointer: %x\n", regs->eip);
+ dump_backtrace(12);
+ asm("hlt");
+ for (;;)
+ ;
+ EOI(0xE - 8);
+}*/
+
+static inline void io_wait(void) { outb(0x80, 0); }
+
+#define ICW1_ICW4 0x01 /* ICW4 (not) needed */
+#define ICW1_SINGLE 0x02 /* Single (cascade) mode */
+#define ICW1_INTERVAL4 0x04 /* Call address interval 4 (8) */
+#define ICW1_LEVEL 0x08 /* Level triggered (edge) mode */
+#define ICW1_INIT 0x10 /* Initialization - required! */
+
+#define ICW4_8086 0x01 /* 8086/88 (MCS-80/85) mode */
+#define ICW4_AUTO 0x02 /* Auto (normal) EOI */
+#define ICW4_BUF_SLAVE 0x08 /* Buffered mode/slave */
+#define ICW4_BUF_MASTER 0x0C /* Buffered mode/master */
+#define ICW4_SFNM 0x10 /* Special fully nested (not) */
+
+void PIC_remap(int offset) {
+ unsigned char a1, a2;
+ a1 = inb(MASTER_PIC_DATA_PORT);
+ a2 = inb(SLAVE_PIC_DATA_PORT);
+
+ // Send ICW1 and tell the PIC that we will issue a ICW4
+ // Since there is no ICW1_SINGLE sent to indicate it is cascaded
+ // it means we will issue a ICW3.
+ outb(MASTER_PIC_COMMAND_PORT, ICW1_INIT | ICW1_ICW4);
+ io_wait();
+ outb(SLAVE_PIC_COMMAND_PORT, ICW1_INIT | ICW1_ICW4);
+ io_wait();
+
+ // As a part of ICW2 this sends the offsets(the position to put IRQ0) of the
+ // vector tables.
+ outb(MASTER_PIC_DATA_PORT, offset);
+ io_wait();
+ outb(SLAVE_PIC_DATA_PORT, offset + 0x8);
+ io_wait();
+
+ // This tells the master on which lines it is having slaves
+ outb(MASTER_PIC_DATA_PORT, 4);
+ io_wait();
+ // This tells the slave the cascading identity.
+ outb(SLAVE_PIC_DATA_PORT, 2);
+ io_wait();
+
+ outb(MASTER_PIC_DATA_PORT, ICW4_8086);
+ io_wait();
+ outb(SLAVE_PIC_DATA_PORT, ICW4_8086);
+ io_wait();
+
+ outb(MASTER_PIC_DATA_PORT, a1);
+ outb(SLAVE_PIC_DATA_PORT, a2);
+}
+
+void IRQ_set_mask(unsigned char IRQline) {
+ uint16_t port;
+ uint8_t value;
+ port = (IRQline < 8) ? MASTER_PIC_DATA_PORT : SLAVE_PIC_DATA_PORT;
+ if (IRQline >= 8)
+ IRQline -= 8;
+ value = inb(port) | (1 << IRQline);
+ outb(port, value);
+}
+
+void IRQ_clear_mask(unsigned char IRQline) {
+ uint16_t port;
+ uint8_t value;
+ port = (IRQline < 8) ? MASTER_PIC_DATA_PORT : SLAVE_PIC_DATA_PORT;
+ if (IRQline >= 8) {
+ IRQline -= 8;
+ }
+ value = inb(port) & ~(1 << IRQline);
+ outb(port, value);
+}
+
+void idt_init(void) {
+ install_handler(page_fault, INT_32_TRAP_GATE(0x3), 0xE);
+ install_handler(double_fault, INT_32_TRAP_GATE(0x0), 0x8);
+ install_handler(kernel_general_protection_fault, INT_32_TRAP_GATE(0x0), 0xD);
+
+ PIC_remap(0x20);
+ // IRQ_set_mask(0xc);
+ IRQ_set_mask(0xe);
+ IRQ_clear_mask(2);
+
+ idtr.interrupt_table = (struct IDT_Descriptor **)&IDT_Entry;
+ idtr.size = (sizeof(struct IDT_Descriptor) * IDT_MAX_ENTRY) - 1;
+ load_idtr(&idtr);
+}
diff --git a/cpu/idt.h b/cpu/idt.h
new file mode 100644
index 0000000..853b1e0
--- /dev/null
+++ b/cpu/idt.h
@@ -0,0 +1,76 @@
+typedef struct kernel_registers kernel_registers_t;
+typedef struct registers registers_t;
+#ifndef IDT_H
+#define IDT_H
+#include <cpu/gdt.h>
+#include <cpu/io.h>
+#include <log.h>
+#include <stdint.h>
+#include <stdio.h>
+
+/*
+ * the type_attribute in the IDT_Entry struct
+ * is divded like this
+ * 7 0
+ * +---+---+---+---+---+---+---+---+
+ * | P | DPL | S | GateType |
+ * +---+---+---+---+---+---+---+---+
+ * It is 8 bits(1 byte) long
+ *
+ * P
+ * Present bit. Should be zero for unused
+ * interrupts.
+ *
+ * DPL
+ * Specifices the maximum ring(0 to 3) the
+ * interrupt can be called from.
+ *
+ * S
+ * Storage segment. This should be set to
+ * zero for all interrupt and trap gates.
+ *
+ * GateType
+ * Possible IDT gate types:
+ * 0b0101 0x5 5 80386 32 bit task gate
+ * 0b0110 0x6 6 80286 16-bit interrupt gate
+ * 0b0111 0x7 7 80286 16-bit trap gate
+ * 0b1110 0xE 14 80386 32-bit interrupt gate
+ * 0b1111 0xF 15 80386 32-bit trap gate
+ */
+
+// This enables the present bit.
+#define INT_PRESENT 0x80 /* 0b10000000 */
+
+#define INT_32_TASK_GATE(min_privlege) \
+ (INT_PRESENT | 0x05 | (min_privlege << 5))
+#define INT_16_INTERRUPT_GATE(min_privlege) \
+ (INT_PRESENT | 0x06 | (min_privlege << 5))
+#define INT_16_TRAP_GATE(min_privlege) \
+ (INT_PRESENT | 0x07 | (min_privlege << 5))
+#define INT_32_INTERRUPT_GATE(min_privlege) \
+ (INT_PRESENT | 0x0E | (min_privlege << 5))
+#define INT_32_TRAP_GATE(min_privlege) \
+ (INT_PRESENT | 0x0F | (min_privlege << 5))
+
+struct interrupt_frame;
+
+struct kernel_registers {
+ // uint32_t ds;
+ // uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax;
+ // uint32_t interrupt_number, error_code;
+ uint32_t error_code;
+ uint32_t eip, cs, eflags;
+};
+
+struct registers {
+ uint32_t ds;
+ uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax;
+ uint32_t interrupt_number, error_code;
+ uint32_t eip, cs, eflags, useresp, ss;
+};
+
+void idt_init(void);
+__attribute__((no_caller_saved_registers)) void EOI(unsigned char irq);
+void install_handler(void (*handler_function)(), uint16_t type_attribute,
+ uint8_t entry);
+#endif
diff --git a/cpu/int_syscall.s b/cpu/int_syscall.s
new file mode 100644
index 0000000..8c3c25f
--- /dev/null
+++ b/cpu/int_syscall.s
@@ -0,0 +1,20 @@
+.intel_syntax noprefix
+.global int_syscall
+.extern syscall_function_handler
+int_syscall:
+ push ebp
+ push edi
+ push esi
+ push edx
+ push ecx
+ push ebx
+ push eax
+ call syscall_function_handler
+ add esp, 4
+ pop ebx
+ pop ecx
+ pop edx
+ pop esi
+ pop edi
+ pop ebp
+ iretd
diff --git a/cpu/io.h b/cpu/io.h
new file mode 100644
index 0000000..9c33b66
--- /dev/null
+++ b/cpu/io.h
@@ -0,0 +1,11 @@
+#include <stdint.h>
+
+__attribute__((no_caller_saved_registers)) extern void outsw(uint16_t,
+ uint32_t);
+__attribute__((no_caller_saved_registers)) extern void outb(uint16_t, uint16_t);
+__attribute__((no_caller_saved_registers)) extern uint16_t inb(uint16_t);
+__attribute__((no_caller_saved_registers)) extern void
+rep_outsw(uint16_t count, uint16_t port, volatile void *addy);
+__attribute__((no_caller_saved_registers)) extern void
+rep_insw(uint16_t count, uint16_t port, volatile void *addy);
+extern void jump_usermode(void (*address)(), uint32_t stack_pointer);
diff --git a/cpu/io.s b/cpu/io.s
new file mode 100644
index 0000000..fe370a5
--- /dev/null
+++ b/cpu/io.s
@@ -0,0 +1,121 @@
+.intel_syntax noprefix
+.global outsw
+.global outb
+.global inb
+.global rep_outsw
+.global rep_insw
+.global flush_tss
+.global load_idtr
+
+# ebx, esi, edi, ebp, and esp;
+outsw:
+ push ebp
+ mov ebp, esp
+ push esi
+ mov dx, [ebp + 4+4]
+ mov esi, [ebp + 8+4]
+ outsw
+ pop esi
+ mov esp, ebp
+ pop ebp
+ ret
+
+outb:
+ mov al, [esp + 8]
+ mov dx, [esp + 4]
+ out dx, al
+ ret
+
+inb:
+ mov dx, [esp + 4]
+ in al, dx
+ ret
+
+rep_outsw:
+ push ebp
+ mov ebp, esp
+ push edi
+ mov ecx, [ebp + 4+4] #ECX is counter for OUTSW
+ mov edx, [ebp + 8+4] #Data port, in and out
+ mov edi, [ebp + 12+4] #Memory area
+ rep outsw #in to [RDI]
+ pop edi
+ mov esp, ebp
+ pop ebp
+ ret
+
+rep_insw:
+ push ebp
+ mov ebp, esp
+ push edi
+ mov ecx, [ebp + 4+4] #ECX is counter for INSW
+ mov edx, [ebp + 8+4] #Data port, in and out
+ mov edi, [ebp + 12+4] #Memory area
+ rep insw #in to [RDI]
+ pop edi
+ mov esp, ebp
+ pop ebp
+ ret
+
+flush_tss:
+ mov ax, 40
+ ltr ax
+ ret
+
+load_idtr:
+ mov edx, [esp + 4]
+ lidt [edx]
+ ret
+
+test_user_function:
+ mov eax, 0x00
+ int 0x80
+ mov ecx, 0x03
+ mov ebx, 0x04
+ mov eax, 0x02
+ int 0x80
+ mov ebx, eax
+ mov eax, 0x01
+ int 0x80
+loop:
+ jmp loop
+ ret
+
+.global spin_lock
+.global spin_unlock
+.extern locked
+
+spin_lock:
+ mov eax, 1
+ xchg eax, ebx
+ test eax, eax
+ jnz spin_lock
+ ret
+
+spin_unlock:
+ xor eax, eax
+ xchg eax, ebx
+ ret
+
+
+.global jump_usermode
+jump_usermode:
+ mov ax, (4 * 8) | 3 # user data segment with RPL 3
+ mov ds, ax
+ mov es, ax
+ mov fs, ax
+ mov gs, ax # sysexit sets SS
+
+ # setup wrmsr inputs
+ xor edx, edx # not necessary; set to 0
+ mov eax, 0x100008 # SS=0x10+0x10=0x20, CS=0x8+0x10=0x18
+ mov ecx, 0x174 # MSR specifier: IA32_SYSENTER_CS
+ wrmsr # set sysexit segments
+
+ # setup sysexit inputs
+ mov edx, [esp + 4] # to be loaded into EIP
+ mov ecx, [esp + 8] # to be loaded into ESP
+ mov esp, ecx
+ mov ebp, ecx
+ sti
+ sysexit
diff --git a/cpu/reload_gdt.s b/cpu/reload_gdt.s
new file mode 100644
index 0000000..3a0119b
--- /dev/null
+++ b/cpu/reload_gdt.s
@@ -0,0 +1,17 @@
+.section .text
+.global load_gdt
+
+load_gdt:
+ mov 4(%esp), %eax
+ lgdt (%eax)
+
+ mov $0x10, %eax
+ mov %eax, %ds
+ mov %eax, %es
+ mov %eax, %fs
+ mov %eax, %gs
+ mov %eax, %ss
+ jmp $0x8, $.long_jump
+.long_jump:
+ ret
+
diff --git a/cpu/spinlock.c b/cpu/spinlock.c
new file mode 100644
index 0000000..3f87423
--- /dev/null
+++ b/cpu/spinlock.c
@@ -0,0 +1,2 @@
+#include <stdint.h>
+uint8_t locked;
diff --git a/cpu/spinlock.h b/cpu/spinlock.h
new file mode 100644
index 0000000..93290c4
--- /dev/null
+++ b/cpu/spinlock.h
@@ -0,0 +1,5 @@
+#ifndef SPINLOCK_H
+#define SPINLOCK_H
+void spin_lock(int *l);
+void spin_unlock(int *l);
+#endif
diff --git a/cpu/syscall.c b/cpu/syscall.c
new file mode 100644
index 0000000..19c195f
--- /dev/null
+++ b/cpu/syscall.c
@@ -0,0 +1,174 @@
+// FIXME: Make sure that the args variabel actually points to something
+// valid.
+#include <assert.h>
+#include <cpu/syscall.h>
+#include <drivers/pst.h>
+#include <errno.h>
+#include <fs/tmpfs.h>
+#include <fs/vfs.h>
+#include <kmalloc.h>
+#include <scalls/accept.h>
+#include <scalls/bind.h>
+#include <scalls/mmap.h>
+#include <scalls/msleep.h>
+#include <scalls/ppoll.h>
+#include <scalls/shm.h>
+#include <scalls/socket.h>
+#include <scalls/stat.h>
+#include <scalls/uptime.h>
+#include <stdint.h>
+#include <string.h>
+
+#pragma GCC diagnostic ignored "-Wpedantic"
+
+int syscall_open(SYS_OPEN_PARAMS *args) {
+ char file[256];
+ strcpy(file, args->file);
+ // const char *file = copy_and_allocate_user_string(args->file);
+ int flags = args->flags;
+ int mode = args->mode;
+ int rc = vfs_open(file, flags, mode);
+ // kfree((void *)file);
+ return rc;
+}
+
+int syscall_exec(SYS_EXEC_PARAMS *args) {
+ const char *filename = copy_and_allocate_user_string(args->path);
+
+ int argc = 0;
+ for (; args->argv[argc];) {
+ argc++;
+ }
+
+ char **new_argv = kallocarray(argc + 1, sizeof(char *));
+ for (int i = 0; i < argc; i++)
+ new_argv[i] = copy_and_allocate_user_string(args->argv[i]);
+
+ new_argv[argc] = NULL;
+
+ exec(filename, new_argv);
+ kfree((void *)filename);
+ for (int i = 0; i < argc; i++)
+ kfree(new_argv[i]);
+ kfree(new_argv);
+ return -1;
+}
+
+int syscall_pipe(int fd[2]) {
+ pipe(fd); // FIXME: Error checking
+ return 0;
+}
+
+int syscall_pread(SYS_PREAD_PARAMS *args) {
+ return vfs_pread(args->fd, args->buf, args->count, args->offset);
+}
+
+int syscall_read(SYS_READ_PARAMS *args) {
+ if (!get_vfs_fd(args->fd))
+ return -EBADF;
+ int rc = vfs_pread(args->fd, args->buf, args->count,
+ get_current_task()->file_descriptors[args->fd]->offset);
+ get_current_task()->file_descriptors[args->fd]->offset += rc;
+ return rc;
+}
+
+int syscall_pwrite(SYS_PWRITE_PARAMS *args) {
+ return vfs_pwrite(args->fd, args->buf, args->count, args->offset);
+}
+
+int syscall_write(int fd, const char *buf, size_t count) {
+ if (!get_vfs_fd(fd))
+ return -EBADF;
+ int rc = vfs_pwrite(fd, (char *)buf, count,
+ get_current_task()->file_descriptors[fd]->offset);
+ get_current_task()->file_descriptors[fd]->offset += rc;
+ return rc;
+}
+
+int syscall_dup2(SYS_DUP2_PARAMS *args) {
+ return vfs_dup2(args->org_fd, args->new_fd);
+}
+
+void syscall_exit(int status) {
+ exit(status);
+ assert(0);
+}
+
+void syscall_wait(int *status) {
+ asm("cli");
+ if (!get_current_task()->child) {
+ if (status)
+ *status = -1;
+ return;
+ }
+ if (get_current_task()->child->dead) {
+ if (status)
+ *status = get_current_task()->child_rc;
+ return;
+ }
+ get_current_task()->halts[WAIT_CHILD_HALT] = 1;
+ switch_task();
+ if (status)
+ *status = get_current_task()->child_rc;
+}
+
+int syscall_fork(void) { return fork(); }
+
+int syscall_getpid(void) { return get_current_task()->pid; }
+
+void *align_page(void *a);
+
+int syscall_brk(void *addr) {
+ void *end = get_current_task()->data_segment_end;
+ if (!mmu_allocate_region(end, addr - end, MMU_FLAG_RW))
+ return -ENOMEM;
+ get_current_task()->data_segment_end = align_page(addr);
+ return 0;
+}
+
+void *syscall_sbrk(uintptr_t increment) {
+ asm("cli");
+ void *rc = get_current_task()->data_segment_end;
+ void *n =
+ (void *)((uintptr_t)(get_current_task()->data_segment_end) + increment);
+ int rc2;
+ if (0 > (rc2 = syscall_brk(n)))
+ return (void *)rc2;
+ return rc;
+}
+
+int syscall_close(int fd) { return vfs_close(fd); }
+
+int syscall_openpty(SYS_OPENPTY_PARAMS *args) {
+ assert(is_valid_userpointer(args, sizeof(SYS_OPENPTY_PARAMS)));
+ return openpty(args->amaster, args->aslave, args->name, args->termp,
+ args->winp);
+}
+
+void (*syscall_functions[])() = {
+ (void(*))syscall_open, (void(*))syscall_read,
+ (void(*))syscall_write, (void(*))syscall_pread,
+ (void(*))syscall_pwrite, (void(*))syscall_fork,
+ (void(*))syscall_exec, (void(*))syscall_getpid,
+ (void(*))syscall_exit, (void(*))syscall_wait,
+ (void(*))syscall_brk, (void(*))syscall_sbrk,
+ (void(*))syscall_pipe, (void(*))syscall_dup2,
+ (void(*))syscall_close, (void(*))syscall_openpty,
+ (void(*))syscall_poll, (void(*))syscall_mmap,
+ (void(*))syscall_accept, (void(*))syscall_bind,
+ (void(*))syscall_socket, (void(*))syscall_shm_open,
+ (void(*))syscall_ftruncate, (void(*))syscall_stat,
+ (void(*))syscall_msleep, (void(*))syscall_uptime,
+};
+
+void syscall_function_handler(uint32_t eax, uint32_t arg1, uint32_t arg2,
+ uint32_t arg3, uint32_t arg4, uint32_t arg5) {
+ assert(eax < sizeof(syscall_functions) / sizeof(syscall_functions[0]));
+ syscall_functions[eax](arg1, arg2, arg3, arg4, arg5);
+}
+
+extern void int_syscall(void);
+
+void syscalls_init(void) {
+ install_handler(int_syscall, INT_32_INTERRUPT_GATE(0x3), 0x80);
+}
diff --git a/cpu/syscall.h b/cpu/syscall.h
new file mode 100644
index 0000000..51d50f2
--- /dev/null
+++ b/cpu/syscall.h
@@ -0,0 +1,59 @@
+#include "idt.h"
+#include <stddef.h>
+#include <stdint.h>
+
+void syscalls_init(void);
+
+typedef struct SYS_OPEN_PARAMS {
+ char *file;
+ int flags;
+ int mode;
+} __attribute__((packed)) SYS_OPEN_PARAMS;
+
+typedef struct SYS_PREAD_PARAMS {
+ int fd;
+ void *buf;
+ size_t count;
+ size_t offset;
+} __attribute__((packed)) SYS_PREAD_PARAMS;
+
+typedef struct SYS_READ_PARAMS {
+ int fd;
+ void *buf;
+ size_t count;
+} __attribute__((packed)) SYS_READ_PARAMS;
+
+typedef struct SYS_PWRITE_PARAMS {
+ int fd;
+ void *buf;
+ size_t count;
+ size_t offset;
+} __attribute__((packed)) SYS_PWRITE_PARAMS;
+
+typedef struct SYS_WRITE_PARAMS {
+ int fd;
+ void *buf;
+ size_t count;
+} __attribute__((packed)) SYS_WRITE_PARAMS;
+
+typedef struct SYS_EXEC_PARAMS {
+ char *path;
+ char **argv;
+} __attribute__((packed)) SYS_EXEC_PARAMS;
+
+typedef struct SYS_WAIT_PARAMS {
+ int *status;
+} __attribute__((packed)) SYS_WAIT_PARAMS;
+
+typedef struct SYS_DUP2_PARAMS {
+ int org_fd;
+ int new_fd;
+} __attribute__((packed)) SYS_DUP2_PARAMS;
+
+typedef struct SYS_OPENPTY_PARAMS {
+ int *amaster;
+ int *aslave;
+ char *name;
+ /*const struct termios*/ void *termp;
+ /*const struct winsize*/ void *winp;
+} __attribute__((packed)) SYS_OPENPTY_PARAMS;
diff --git a/crypto/ChaCha20/chacha20.c b/crypto/ChaCha20/chacha20.c
new file mode 100644
index 0000000..5bf7aa2
--- /dev/null
+++ b/crypto/ChaCha20/chacha20.c
@@ -0,0 +1,29 @@
+#include "chacha20.h"
+
+#define ROTL(a, b) (((a) << (b)) | ((a) >> (32 - (b))))
+#define QR(a, b, c, d) \
+ (a += b, d ^= a, d = ROTL(d, 16), c += d, b ^= c, b = ROTL(b, 12), \
+ a += b, d ^= a, d = ROTL(d, 8), c += d, b ^= c, b = ROTL(b, 7))
+#define ROUNDS 20
+
+void chacha_block(uint32_t out[16], uint32_t const in[16])
+{
+ int i;
+ uint32_t x[16];
+
+ for (i = 0; i < 16; ++i)
+ x[i] = in[i];
+ for (i = 0; i < ROUNDS; i += 2) {
+ QR(x[0], x[4], x[8], x[12]);
+ QR(x[1], x[5], x[9], x[13]);
+ QR(x[2], x[6], x[10], x[14]);
+ QR(x[3], x[7], x[11], x[15]);
+
+ QR(x[0], x[5], x[10], x[15]);
+ QR(x[1], x[6], x[11], x[12]);
+ QR(x[2], x[7], x[8], x[13]);
+ QR(x[3], x[4], x[9], x[14]);
+ }
+ for (i = 0; i < 16; ++i)
+ out[i] = x[i] + in[i];
+}
diff --git a/crypto/ChaCha20/chacha20.h b/crypto/ChaCha20/chacha20.h
new file mode 100644
index 0000000..17532f3
--- /dev/null
+++ b/crypto/ChaCha20/chacha20.h
@@ -0,0 +1,15 @@
+#ifndef CHACHA20_H
+#define CHACHA20_H
+#include <stdint.h>
+
+#define KEY 4
+#define KEY_SIZE 8*sizeof(uint32_t)
+#define COUNT 12
+#define COUNT_SIZE sizeof(uint32_t)
+#define COUNT_MAX (0x100000000-1) // 2^32 - 1
+#define NONCE 13
+#define NONCE_SIZE 2*sizeof(uint32_t)
+#define BLOCK_SIZE 16*sizeof(uint32_t)
+
+void chacha_block(uint32_t out[16], uint32_t const in[16]);
+#endif
diff --git a/crypto/SHA1 b/crypto/SHA1
new file mode 160000
+Subproject 237ea7023cad8402932dfbde337d69e5f4d515f
diff --git a/drivers/ata.c b/drivers/ata.c
new file mode 100644
index 0000000..fd9b504
--- /dev/null
+++ b/drivers/ata.c
@@ -0,0 +1,253 @@
+#include <assert.h>
+#include <cpu/io.h>
+#include <drivers/ata.h>
+#include <drivers/pit.h>
+
+#define PRIMARY_BUS_BASEPORT 0x1F0
+#define SECONDAY_BUS_BASEPORT 0x170
+
+#define PRIMARY_BUS_IRQ 14
+#define SECONDAY_BUS_IRQ 15
+
+#define STATUS_PORT 7
+#define COMMAND_PORT 7
+#define DRIVE_SELECT 6
+#define LBAhi 5
+#define LBAmid 4
+#define LBAlo 3
+#define SECTOR_COUNT 2
+#define DATA_PORT 0
+
+#define IDENTIFY 0xEC
+#define READ_SECTORS 0x20
+#define WRITE_SECTORS 0x30
+#define CACHE_FLUSH 0xE7
+
+#define STATUS_BSY ((1 << 7))
+#define STATUS_DF ((1 << 5))
+#define STATUS_DRQ ((1 << 3))
+#define STATUS_ERR ((1 << 0))
+
+uint32_t io_base;
+
+unsigned char read_buffer[SECTOR_SIZE];
+
+void select_drive(uint8_t master_slave) {
+ outb(io_base + DRIVE_SELECT, (master_slave) ? 0xA0 : 0xB0);
+}
+
+int identify(int master_slave) {
+ select_drive(master_slave);
+ outb(io_base + SECTOR_COUNT, 0);
+ outb(io_base + LBAlo, 0);
+ outb(io_base + LBAmid, 0);
+ outb(io_base + LBAhi, 0);
+ outb(io_base + COMMAND_PORT, IDENTIFY);
+ if (0 == inb(io_base + STATUS_PORT))
+ return 0; // Drive does not exist
+
+ for (; 0 != (inb(io_base + STATUS_PORT) & STATUS_BSY);)
+ ;
+
+ // Because of some ATAPI drives that do not
+ // follow spec, at this point we need to check
+ // the LBAmid and LBAhi ports to see if they are
+ // non-zero. If so, the drive is not ATA, and we
+ // should stop polling.
+ if (0 != inb(io_base + LBAmid) || 0 != inb(io_base + LBAhi)) {
+ klog("Drive is not ATA.", LOG_ERROR);
+ return -1;
+ }
+
+ for (uint16_t status;;) {
+ status = inb(io_base + STATUS_PORT);
+
+ if (1 == (status & STATUS_ERR)) {
+ klog("Drive ERR set.", LOG_ERROR);
+ return -2;
+ }
+
+ if ((status & STATUS_DRQ))
+ break;
+ }
+
+ // The data is ready to read from the Data
+ // port (0x1F0). Read 256 16-bit values,
+ // and store them.
+ // TODO: This returns some intreasting information.
+ // https://wiki.osdev.org/ATA_PIO_Mode#Interesting_information_returned_by_IDENTIFY
+ uint16_t array[256];
+ rep_insw(1 * SECTOR_SIZE / 16, io_base + DATA_PORT, array);
+ return 1;
+}
+
+int poll_status(void) {
+ for (uint16_t status;;) {
+ // Read the Regular Status port until...
+ // We read this 15 times to give some
+ // time for the drive to catch up.
+ for (int n = 0; n < 15; n++)
+ status = inb(io_base + STATUS_PORT);
+
+ // ERR or
+ // DF sets
+ if ((status & STATUS_ERR) || (status & STATUS_DF)) {
+ klog("Drive error set.", LOG_ERROR);
+ return 0;
+ }
+
+ // BSY clears
+ // DRQ sets
+ if (0 == (status & STATUS_BSY) && 0 != (status & STATUS_DRQ))
+ break;
+ }
+ return 1;
+}
+
+// Instructions from: https://wiki.osdev.org/ATA_PIO_Mode#28_bit_PIO
+void __attribute__((optimize("O0")))
+setup_drive_for_command(uint32_t lba, uint32_t sector_count) {
+ // 1. Send 0xE0 for the "master" or 0xF0 for
+ // the "slave", ORed with the highest 4 bits
+ // of the LBA to port 0x1F6
+ outb(io_base + DRIVE_SELECT, 0xE0 | (0 << 4) | ((lba >> 24) & 0x0F));
+
+ // 2. Send a NULL byte to port 0x1F1, if you
+ // like (it is ignored and wastes
+ // lots of CPU time)
+
+ // NOP
+
+ // 3. Send the sectorcount to port 0x1F2
+ outb(io_base + SECTOR_COUNT, sector_count);
+
+ // 4. Send the low 8 bits of the LBA to port 0x1F3
+ outb(io_base + LBAlo, (lba >> 0) & 0xFF);
+
+ // 5. Send the next 8 bits of the LBA to port 0x1F4
+ outb(io_base + LBAmid, (lba >> 8) & 0xFF);
+
+ // 6. Send the next 8 bits of the LBA to port 0x1F5
+ outb(io_base + LBAhi, (lba >> 16) & 0xFF);
+}
+
+void delayed_rep_outsw(size_t n, uint16_t port, volatile uint8_t *buffer) {
+ for (volatile size_t i = 0; i < n; i++) {
+ outsw(port, (uint32_t)buffer);
+ buffer += 2;
+ // outsw(port, buffer);
+ }
+}
+
+void __attribute__((optimize("O0")))
+ata_write_lba28(uint32_t lba, uint32_t sector_count,
+ volatile const uint8_t *buffer) {
+ setup_drive_for_command(lba, sector_count);
+
+ outb(io_base + COMMAND_PORT, WRITE_SECTORS);
+
+ for (volatile uint32_t i = 0; i < sector_count; i++) {
+ if (!poll_status()) {
+ // FIXME: Fail properly
+ for (;;)
+ ;
+ }
+
+ delayed_rep_outsw(256, io_base + DATA_PORT,
+ (void *)((uint32_t)buffer + i * 256));
+ }
+
+ // Cache flush
+ outb(io_base + COMMAND_PORT, CACHE_FLUSH);
+
+ // Wait for BSY to clear
+ for (;;) {
+ uint16_t status = inb(io_base + STATUS_PORT);
+ if (!(status & STATUS_BSY))
+ break;
+ }
+}
+
+// Instructions from: https://wiki.osdev.org/ATA_PIO_Mode#28_bit_PIO
+void __attribute__((optimize("O0")))
+ata_read_lba28(uint32_t lba, uint32_t sector_count, volatile void *address) {
+ // Step 1-6 is done in this function.
+ setup_drive_for_command(lba, sector_count);
+
+ // 7. Send the "READ SECTORS" command to port 0x17F
+ outb(io_base + COMMAND_PORT, READ_SECTORS);
+
+ // 8. Wait for an IRQ or poll.
+
+ // This step can be found in the for loop
+
+ // 9. Transfer 256 16-bit values, a uint16_t at a time,
+ // into your buffer from I/O port 0x1F0
+ for (volatile uint32_t i = 0; i < sector_count; i++) {
+ // 10. Then loop back to waiting for the next IRQ
+ // or poll again for each successive sector.
+ // 8. Wait for an IRQ or poll.
+ if (!poll_status()) {
+ // FIXME: Fail properly
+ for (;;)
+ ;
+ }
+ rep_insw(256, io_base + DATA_PORT, (void *)((uint32_t)address + i * 256));
+ }
+}
+
+void ata_init(void) {
+ io_base = PRIMARY_BUS_BASEPORT;
+
+ // Before sending any data to the IO ports,
+ // read the Regular Status byte. The value
+ // 0xFF is an illegal status value, and
+ // indicates that the bus has no drives
+ if (0xFF == inb(io_base + STATUS_PORT)) {
+ klog("Bus has no drives", LOG_ERROR);
+ }
+
+ // Issue IDENTIFY command
+ select_drive(1);
+}
+
+void __attribute__((optimize("O0")))
+read_lba(uint32_t lba, void *address, size_t size, size_t offset) {
+ uintptr_t ptr = (uintptr_t)address;
+ lba += offset / SECTOR_SIZE;
+ offset = offset % SECTOR_SIZE;
+ asm("cli");
+ size_t total_read = 0;
+ for (int i = 0; size > 0; i++) {
+ uint32_t read_len =
+ (SECTOR_SIZE < (size + offset)) ? (SECTOR_SIZE - offset) : size;
+ ata_read_lba28(lba + i, 1, read_buffer);
+ memcpy((void *)ptr, read_buffer + offset, read_len);
+ size -= read_len;
+ total_read += read_len;
+ ptr += read_len;
+ offset = 0;
+ }
+}
+
+void write_lba(uint32_t lba, volatile void *address, size_t size,
+ size_t offset) {
+ uintptr_t ptr = (uintptr_t)address;
+ lba += offset / SECTOR_SIZE;
+ offset = offset % SECTOR_SIZE;
+ size_t total_write = 0;
+ uint8_t sector_buffer[512];
+ for (int i = 0; size > 0; i++) {
+ ata_read_lba28(lba + i, 1, sector_buffer);
+ uint32_t write_len =
+ (SECTOR_SIZE < (size + offset)) ? (SECTOR_SIZE - offset) : size;
+
+ memcpy(sector_buffer + offset, (void *)ptr, write_len);
+ ata_write_lba28(lba + i, 1, sector_buffer);
+
+ size -= write_len;
+ total_write += write_len;
+ ptr += write_len;
+ offset = 0;
+ }
+}
diff --git a/drivers/ata.h b/drivers/ata.h
new file mode 100644
index 0000000..3e88d7f
--- /dev/null
+++ b/drivers/ata.h
@@ -0,0 +1,16 @@
+#include "../cpu/idt.h"
+#include <stddef.h>
+
+#define SECTOR_SIZE 512
+
+void ata_init(void);
+
+void read_drive_chs(uint8_t head_index, uint8_t sector_count,
+ uint8_t sector_index, uint8_t cylinder_low_value,
+ uint8_t cylinder_high_value, void *address);
+void read_drive_lba(uint32_t lba, uint8_t sector_count, void *address);
+void read_lba(uint32_t lba, void *address, size_t size, size_t offset);
+void write_lba(uint32_t lba, volatile void *address, size_t size,
+ size_t offset);
+void ata_write_lba28(uint32_t lba, uint32_t sector_count,
+ volatile const uint8_t *buffer);
diff --git a/drivers/keyboard.c b/drivers/keyboard.c
new file mode 100644
index 0000000..8c96606
--- /dev/null
+++ b/drivers/keyboard.c
@@ -0,0 +1,188 @@
+#include <assert.h>
+#include <drivers/keyboard.h>
+#include <errno.h>
+#include <fs/devfs.h>
+#include <fs/fifo.h>
+#include <fs/vfs.h>
+#include <sched/scheduler.h>
+#include <stdint.h>
+
+#define PS2_REG_DATA 0x60
+#define PS2_REG_STATUS 0x64
+#define PS2_REG_COMMAND 0x64
+
+#define PS2_CMD_ENABLE_FIRST_PORT 0xAE // no rsp
+
+#define PS2_CMD_TEST_CONTROLLER 0xAA // has rsp
+
+#define PS2_RSP_TEST_PASSED 0x55
+#define PS2_RSP_TEST_FAILED 0xFC
+
+#define PS2_CMD_SET_SCANCODE 0xF0 // has rsp
+#define PS2_KB_ACK 0xFA
+#define PS2_KB_RESEND 0xFE
+
+#define PS2_CMD_SET_MAKE_RELEASE 0xF8 // has rsp
+
+uint8_t kb_scancodes[3] = {0x43, 0x41, 0x3f};
+
+FIFO_FILE *keyboard_fifo;
+
+uint8_t ascii_table[] = {
+ 'e', '\x1B', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', 8,
+ '\t',
+
+ 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p',
+ // 0, // [
+ // 0, // ]
+ // 0,
+ // 0, // ?
+ '[', ']',
+ '\n', // ENTER
+ 'C',
+
+ 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l',
+ ';', // ;
+ '\'', // ;
+ '`', // ;
+ 'D', // LEFT SHIFT
+ '\\', // ;
+ 'z', 'x', 'c', 'v', 'b', 'n', 'm',
+ ',', // ;
+ '.', // ;
+ '/', // ;
+ 'U', // ;
+ 'U', // ;
+ 'U', // ;
+ ' ', // ;
+};
+
+uint8_t capital_ascii_table[] = {
+ 'e', '\x1B', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', 8,
+ '\t',
+
+ 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P',
+ // 0, // [
+ // 0, // ]
+ // 0,
+ // 0, // ?
+ '{', '}',
+ '\n', // ENTER
+ 'C',
+
+ 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L',
+ ':', // ;
+ '\"', // ;
+ '~', // ;
+ 'D', // LEFT SHIFT
+ '\\', // ;
+ 'Z', 'X', 'C', 'V', 'B', 'N', 'M',
+ '<', // ;
+ '>', // ;
+ '?', // ;
+ 'U', // ;
+ 'U', // ;
+ 'U', // ;
+ ' ', // ;
+};
+
+vfs_inode_t *kb_inode;
+
+uint8_t keyboard_to_ascii(uint16_t key, uint8_t capital) {
+ if ((key & 0xFF) > sizeof(ascii_table))
+ return 'U';
+ if (capital)
+ return capital_ascii_table[key & 0xFF];
+ else
+ return ascii_table[key & 0xFF];
+}
+
+uint8_t is_shift_down = 0;
+uint8_t is_alt_down = 0;
+
+struct KEY_EVENT {
+ char c;
+ uint8_t mode; // (shift (0 bit)) (alt (1 bit))
+ uint8_t release; // 0 pressed, 1 released
+};
+
+extern process_t *ready_queue;
+__attribute__((interrupt)) void
+int_keyboard(__attribute__((unused)) struct interrupt_frame *frame) {
+ outb(0x20, 0x20);
+ uint16_t c;
+ c = inb(PS2_REG_DATA);
+ int released = 0;
+ if (c & 0x80) {
+ switch ((c & ~(0x80)) & 0xFF) {
+ case 0x2A: // Left shift
+ case 0x36: // Right shift
+ is_shift_down = 0;
+ return;
+ case 0x38:
+ is_alt_down = 0;
+ return;
+ }
+ released = 1;
+ } else {
+ switch (c & 0xFF) {
+ case 0x2A: // Left shift
+ case 0x36: // Right shift
+ is_shift_down = 1;
+ return;
+ case 0x38:
+ is_alt_down = 1;
+ return;
+ }
+ released = 0;
+ }
+ unsigned char a = keyboard_to_ascii((c & ~(0x80)) & 0xFF, is_shift_down);
+ struct KEY_EVENT ev;
+ ev.c = a;
+ ev.release = released;
+ ev.mode = 0;
+ ev.mode |= is_shift_down << 0;
+ ev.mode |= is_alt_down << 1;
+ fifo_object_write((uint8_t *)&ev, 0, sizeof(ev), keyboard_fifo);
+ kb_inode->has_data = keyboard_fifo->has_data;
+}
+
+#define PS2_WAIT_RECV \
+ { \
+ for (;;) { \
+ uint8_t status = inb(PS2_REG_STATUS); \
+ if (status & 0x1) \
+ break; \
+ } \
+ }
+
+#define PS2_WAIT_SEND \
+ { \
+ for (;;) { \
+ uint8_t status = inb(PS2_REG_STATUS); \
+ if (!(status & (0x1 << 1))) \
+ break; \
+ } \
+ }
+
+void install_keyboard(void) {
+ keyboard_fifo = create_fifo_object();
+ install_handler(int_keyboard, INT_32_INTERRUPT_GATE(0x3), 0x21);
+}
+
+int keyboard_read(uint8_t *buffer, uint64_t offset, uint64_t len,
+ vfs_fd_t *fd) {
+ (void)offset;
+
+ if (0 == fd->inode->has_data) {
+ return -EAGAIN;
+ }
+ int rc = fifo_object_read(buffer, 0, len, keyboard_fifo);
+ fd->inode->has_data = keyboard_fifo->has_data;
+ return rc;
+}
+
+void add_keyboard(void) {
+ kb_inode = devfs_add_file("/keyboard", keyboard_read, NULL, NULL, 0, 0,
+ FS_TYPE_CHAR_DEVICE);
+}
diff --git a/drivers/keyboard.h b/drivers/keyboard.h
new file mode 100644
index 0000000..4b76f22
--- /dev/null
+++ b/drivers/keyboard.h
@@ -0,0 +1,11 @@
+#ifndef KEYBOARD_H
+#define KEYBOARD_H
+
+#include <stdint.h>
+#include <cpu/io.h>
+#include <cpu/idt.h>
+
+void install_keyboard(void);
+void add_keyboard(void);
+
+#endif
diff --git a/drivers/mouse.c b/drivers/mouse.c
new file mode 100644
index 0000000..23619a0
--- /dev/null
+++ b/drivers/mouse.c
@@ -0,0 +1,144 @@
+#include <cpu/idt.h>
+#include <drivers/mouse.h>
+#include <fs/devfs.h>
+#include <fs/fifo.h>
+#include <fs/vfs.h>
+#include <stdint.h>
+
+uint8_t mouse_cycle = 0; // unsigned char
+uint8_t mouse_uint8_t[3]; // signed char
+uint8_t mouse_x = 0; // signed char
+uint8_t mouse_y = 0; // signed char
+vfs_inode_t *mouse_inode;
+vfs_fd_t *mouse_fd;
+
+struct mouse_event {
+ uint8_t buttons;
+ uint8_t x;
+ uint8_t y;
+};
+
+int fs_mouse_write(uint8_t *buffer, uint64_t offset, uint64_t len,
+ vfs_fd_t *fd) {
+ int rc = fifo_object_write(buffer, offset, len, fd->inode->internal_object);
+ FIFO_FILE *f = fd->inode->internal_object;
+ mouse_inode->has_data = f->has_data;
+ return rc;
+}
+
+int fs_mouse_read(uint8_t *buffer, uint64_t offset, uint64_t len,
+ vfs_fd_t *fd) {
+ FIFO_FILE *f = fd->inode->internal_object;
+ if (!mouse_inode->has_data)
+ return 0;
+ int rc = fifo_object_read(buffer, offset, len, f);
+ mouse_inode->has_data = f->has_data;
+ return rc;
+}
+
+void add_mouse(void) {
+ mouse_inode = devfs_add_file("/mouse", fs_mouse_read, fs_mouse_write, NULL, 0,
+ 0, FS_TYPE_CHAR_DEVICE);
+ mouse_inode->internal_object = create_fifo_object();
+ // Don't look at this
+ int fd = vfs_open("/dev/mouse", O_RDWR, 0);
+ mouse_fd = get_vfs_fd(fd);
+ get_current_task()->file_descriptors[fd] = NULL;
+}
+
+__attribute__((interrupt)) void what(registers_t *r) { EOI(0xe); }
+
+__attribute__((interrupt)) void int_mouse(registers_t *r) {
+ (void)r;
+ EOI(12);
+ switch (mouse_cycle) {
+ case 0:
+ mouse_uint8_t[0] = inb(0x60);
+ if(!(mouse_uint8_t[0] & (1 << 3))) {
+ mouse_cycle = 0;
+ return;
+ }
+ mouse_cycle++;
+ break;
+ case 1:
+ mouse_uint8_t[1] = inb(0x60);
+ mouse_cycle++;
+ break;
+ case 2:
+ mouse_uint8_t[2] = inb(0x60);
+ mouse_x = mouse_uint8_t[1];
+ mouse_y = mouse_uint8_t[2];
+ mouse_cycle = 0;
+ struct mouse_event e;
+ e.buttons = mouse_uint8_t[0];
+ e.x = mouse_x;
+ e.y = mouse_y;
+ raw_vfs_pwrite(mouse_fd, &e, sizeof(e), 0);
+ break;
+ }
+}
+
+void mouse_wait(uint8_t a_type) {
+ uint32_t _time_out = 100000;
+ if (a_type == 0) {
+ while (_time_out--) {
+ if ((inb(0x64) & 1) == 1) {
+ return;
+ }
+ }
+ return;
+ } else {
+ while (_time_out--) {
+ if ((inb(0x64) & 2) == 0) {
+ return;
+ }
+ }
+ return;
+ }
+}
+
+void mouse_write(uint8_t a_write) {
+ // Wait to be able to send a command
+ mouse_wait(1);
+ // Tell the mouse we are sending a command
+ outb(0x64, 0xD4);
+ // Wait for the final part
+ mouse_wait(1);
+ // Finally write
+ outb(0x60, a_write);
+}
+
+uint8_t mouse_read() {
+ // Get's response from mouse
+ mouse_wait(0);
+ return inb(0x60);
+}
+
+void install_mouse(void) {
+ uint8_t _status; // unsigned char
+ asm("cli");
+ // Enable the auxiliary mouse device
+ mouse_wait(1);
+ outb(0x64, 0xA8);
+
+ // Enable the interrupts
+ mouse_wait(1);
+ outb(0x64, 0x20);
+ mouse_wait(0);
+ _status = (inb(0x60) | 2);
+ mouse_wait(1);
+ outb(0x64, 0x60);
+ mouse_wait(1);
+ outb(0x60, _status);
+
+ // Tell the mouse to use default settings
+ mouse_write(0xF6);
+ mouse_read(); // Acknowledge
+
+ // Enable the mouse
+ mouse_write(0xF4);
+ mouse_read(); // Acknowledge
+
+ install_handler(int_mouse, INT_32_INTERRUPT_GATE(0x3), 12 + 0x20);
+ install_handler(what, INT_32_INTERRUPT_GATE(0x3), 0xe + 0x20);
+}
diff --git a/drivers/mouse.h b/drivers/mouse.h
new file mode 100644
index 0000000..5248143
--- /dev/null
+++ b/drivers/mouse.h
@@ -0,0 +1,5 @@
+#ifndef MOUSE_H
+#define MOUSE_H
+void install_mouse(void);
+void add_mouse(void);
+#endif
diff --git a/drivers/pit.c b/drivers/pit.c
new file mode 100644
index 0000000..711883c
--- /dev/null
+++ b/drivers/pit.c
@@ -0,0 +1,55 @@
+#include "pit.h"
+
+#define PIT_IO_CHANNEL_0 0x40
+#define PIT_IO_MODE_COMMAND 0x43
+
+uint64_t clock_num_ms_ticks = 0;
+uint64_t pit_counter = 0;
+uint16_t hertz;
+
+uint64_t pit_num_ms(void) { return clock_num_ms_ticks; }
+
+uint16_t read_pit_count(void) {
+ uint16_t count = 0;
+
+ outb(PIT_IO_MODE_COMMAND, 0x0 /*0b00000000*/);
+
+ count = inb(PIT_IO_CHANNEL_0);
+ count |= inb(PIT_IO_CHANNEL_0) << 8;
+
+ return count;
+}
+
+void set_pit_count(uint16_t hertz) {
+ uint16_t divisor = 1193180 / hertz;
+
+ /*
+ * 0b00110110
+ * ^^
+ * channel - 0
+ * ^^
+ * r/w mode - LSB then MSB
+ * ^^^
+ * mode - 3 Square Wave Mode
+ * ^
+ * BCD - no
+ */
+ outb(PIT_IO_MODE_COMMAND, 0x36 /*0b00110110*/);
+ outb(PIT_IO_CHANNEL_0, divisor & 0xFF);
+ outb(PIT_IO_CHANNEL_0, (divisor & 0xFF00) >> 8);
+}
+
+__attribute__((interrupt)) void
+int_clock(__attribute__((unused)) struct interrupt_frame *frame) {
+ outb(0x20, 0x20);
+ pit_counter++;
+ if (pit_counter >= hertz / 1000) {
+ pit_counter = 0;
+ clock_num_ms_ticks++;
+ }
+ switch_task();
+}
+
+void pit_install(void) {
+ install_handler(int_clock, INT_32_INTERRUPT_GATE(0x0), 0x20);
+}
diff --git a/drivers/pit.h b/drivers/pit.h
new file mode 100644
index 0000000..8d9ce98
--- /dev/null
+++ b/drivers/pit.h
@@ -0,0 +1,12 @@
+#ifndef PIT_H
+#define PIT_H
+#include <cpu/idt.h>
+#include <cpu/io.h>
+#include <sched/scheduler.h>
+#include <stdint.h>
+#include <stdio.h>
+
+void pit_install(void);
+void set_pit_count(uint16_t hertz);
+uint64_t pit_num_ms(void);
+#endif
diff --git a/drivers/pst.c b/drivers/pst.c
new file mode 100644
index 0000000..d063ec9
--- /dev/null
+++ b/drivers/pst.c
@@ -0,0 +1,17 @@
+#include <drivers/pst.h>
+#include <fs/tmpfs.h>
+
+int openpty(int *amaster, int *aslave, char *name,
+ /*const struct termios*/ void *termp,
+ /*const struct winsize*/ void *winp) {
+ (void)name;
+ (void)termp;
+ (void) winp;
+ int fd[2];
+ pipe(fd); // This depends upon that pipe will support read and write
+ // through the same fd. In reality this should not be the
+ // case.
+ *amaster = fd[0];
+ *aslave = fd[1];
+ return 0;
+}
diff --git a/drivers/pst.h b/drivers/pst.h
new file mode 100644
index 0000000..e8fdfaa
--- /dev/null
+++ b/drivers/pst.h
@@ -0,0 +1,7 @@
+#ifndef PST_H
+#define PST_H
+#include "../fs/vfs.h"
+
+int openpty(int *amaster, int *aslave, char *name, /*const struct termios*/ void *termp,
+ /*const struct winsize*/ void *winp);
+#endif
diff --git a/drivers/serial.c b/drivers/serial.c
new file mode 100644
index 0000000..549d852
--- /dev/null
+++ b/drivers/serial.c
@@ -0,0 +1,35 @@
+#include "cpu/io.h"
+
+#define PORT 0x3f8 // COM1
+
+int serial_init(void) {
+ outb(PORT + 1, 0x00); // Disable all interrupts
+ outb(PORT + 3, 0x80); // Enable DLAB (set baud rate divisor)
+ outb(PORT + 0, 0x03); // Set divisor to 3 (lo byte) 38400 baud
+ outb(PORT + 1, 0x00); // (hi byte)
+ outb(PORT + 3, 0x03); // 8 bits, no parity, one stop bit
+ outb(PORT + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold
+ outb(PORT + 4, 0x0B); // IRQs enabled, RTS/DSR set
+ outb(PORT + 4, 0x1E); // Set in loopback mode, test the serial chip
+ outb(PORT + 0, 0xAE); // Test serial chip (send byte 0xAE and check if serial
+ // returns same byte)
+
+ // Check if serial is faulty (i.e: not same byte as sent)
+ if (inb(PORT + 0) != 0xAE) {
+ return 1;
+ }
+
+ // If serial is not faulty set it in normal operation mode
+ // (not-loopback with IRQs enabled and OUT#1 and OUT#2 bits enabled)
+ outb(PORT + 4, 0x0F);
+ return 0;
+}
+
+int is_transmit_empty() { return inb(PORT + 5) & 0x20; }
+
+void write_serial(char a) {
+ while (is_transmit_empty() == 0)
+ ;
+
+ outb(PORT, a);
+}
diff --git a/drivers/serial.h b/drivers/serial.h
new file mode 100644
index 0000000..327765b
--- /dev/null
+++ b/drivers/serial.h
@@ -0,0 +1,2 @@
+int serial_init(void);
+void write_serial(char a);
diff --git a/drivers/vbe.c b/drivers/vbe.c
new file mode 100644
index 0000000..97f5507
--- /dev/null
+++ b/drivers/vbe.c
@@ -0,0 +1,50 @@
+#include <assert.h>
+#include <drivers/vbe.h>
+#include <fs/devfs.h>
+#include <fs/vfs.h>
+#include <mmu.h>
+#include <stdio.h>
+
+uint8_t *framebuffer;
+uint32_t framebuffer_physical;
+uint32_t framebuffer_width;
+uint32_t framebuffer_height;
+uint64_t framebuffer_size;
+
+vfs_vm_object_t vbe_vm_object;
+
+#define CHECK_FLAG(flags, bit) ((flags) & (1 << (bit)))
+
+void display_driver_init(multiboot_info_t *mbi) {
+ assert(CHECK_FLAG(mbi->flags, 12));
+ framebuffer_width = mbi->framebuffer_width;
+ framebuffer_height = mbi->framebuffer_height;
+
+ uint32_t bits_pp = mbi->framebuffer_bpp;
+ uint32_t bytes_pp = (bits_pp / 8) + (8 - (bits_pp % 8));
+
+ framebuffer_size = bytes_pp * framebuffer_width * framebuffer_height;
+
+ framebuffer_physical = mbi->framebuffer_addr;
+ framebuffer =
+ mmu_map_frames((void *)(uint32_t)mbi->framebuffer_addr, framebuffer_size);
+}
+
+vfs_vm_object_t *vbe_get_vm_object(uint64_t length, uint64_t offset,
+ vfs_fd_t *fd) {
+ (void)fd;
+ (void)length;
+ (void)offset;
+ vbe_vm_object.size = framebuffer_size;
+ int n = (uintptr_t)align_page((void *)(uint32_t)framebuffer_size) / 0x1000;
+ vbe_vm_object.object = kmalloc(sizeof(void *) * n);
+ for (int i = 0; i < n; i++) {
+ vbe_vm_object.object[i] = (void *)framebuffer_physical + (i * 0x1000);
+ }
+ return &vbe_vm_object;
+}
+
+void add_vbe_device(void) {
+ devfs_add_file("/vbe", NULL, NULL, vbe_get_vm_object, 1, 1,
+ FS_TYPE_BLOCK_DEVICE);
+}
diff --git a/drivers/vbe.h b/drivers/vbe.h
new file mode 100644
index 0000000..4df2221
--- /dev/null
+++ b/drivers/vbe.h
@@ -0,0 +1,7 @@
+#ifndef VBE_H
+#define VBE_H
+#include <multiboot.h>
+void display_driver_init(multiboot_info_t *mb);
+void display_driver_cross(multiboot_info_t *mbi);
+void add_vbe_device(void);
+#endif // VBE_H
diff --git a/elf.c b/elf.c
new file mode 100644
index 0000000..ca8f89d
--- /dev/null
+++ b/elf.c
@@ -0,0 +1,73 @@
+#include <assert.h>
+#include <crypto/SHA1/sha1.h>
+#include <elf.h>
+#include <sched/scheduler.h>
+#include <stddef.h>
+#include <stdint.h>
+
+void *load_elf_file(const char *f, uint32_t *ds) {
+ // ELFHeader *header = kmalloc(sizeof(ELFHeader));
+ ELFHeader header;
+ int fd = vfs_open(f, O_RDONLY, 0);
+ if (fd < 0) {
+ return NULL;
+ }
+
+ if (sizeof(header) != vfs_pread(fd, &header, sizeof(header), 0)) {
+ return NULL;
+ }
+
+ if (0 != memcmp(header.e_ident, "\x7F\x45\x4C\x46" /* "\x7FELF" */, 4)) {
+ klog("Incorrect ELF signature", LOG_ERROR);
+ return NULL;
+ }
+
+ if (0 > fd) {
+ return NULL;
+ }
+ Elf32_Phdr program_header;
+ assert(sizeof(program_header) == header.e_phentsize);
+ uint32_t header_offset = header.e_phoff;
+ uintptr_t end_of_code = 0;
+ for (int i = 0; i < header.e_phnum;
+ i++, header_offset += header.e_phentsize) {
+ if (0 >=
+ vfs_pread(fd, &program_header, sizeof(program_header), header_offset)) {
+ return NULL;
+ }
+
+ // FIXME: Only one type is supported, which is 1(load). More should be
+ // added.
+ assert(1 == program_header.p_type);
+
+ // 1. Clear p_memsz bytes at p_vaddr to 0.(We also allocate frames for
+ // that range)
+ uint32_t p_memsz = program_header.p_memsz;
+ uint32_t p_vaddr = program_header.p_vaddr;
+
+ uint32_t pages_to_allocate =
+ (uint32_t)align_page((void *)(p_vaddr + p_memsz));
+ pages_to_allocate -= p_vaddr - (p_vaddr % 0x1000);
+ pages_to_allocate /= 0x1000;
+
+ mmu_allocate_region((void *)p_vaddr, pages_to_allocate * 0x1000,
+ MMU_FLAG_RW);
+
+ flush_tlb();
+
+ uintptr_t e = program_header.p_vaddr + program_header.p_memsz;
+ if (e > end_of_code)
+ end_of_code = e;
+
+ memset((void *)program_header.p_vaddr, 0, program_header.p_memsz);
+
+ // 2. Copy p_filesz bytes from p_offset to p_vaddr
+ int rc = vfs_pread(fd, (void *)program_header.p_vaddr,
+ program_header.p_filesz, program_header.p_offset);
+
+ assert(rc == (int)program_header.p_filesz);
+ }
+ *ds = end_of_code;
+ vfs_close(fd);
+ return (void *)header.e_entry;
+}
diff --git a/elf.h b/elf.h
new file mode 100644
index 0000000..452ddbd
--- /dev/null
+++ b/elf.h
@@ -0,0 +1,99 @@
+#ifndef ELF_H
+#define ELF_H
+#include <stdint.h>
+#include <mmu.h>
+#include <fs/vfs.h>
+#include <assert.h>
+
+#define ET_NONE 0 // No file type
+#define ET_REL 1 // Relocatable file
+#define ET_EXEC 2 // Executable file
+#define ET_DYN 3 // Shared object file
+#define ET_CORE 4 // Core file
+#define ET_LOPROC 0xff00 // Processor-specific
+#define ET_HIPROC 0xffff // Processor-specific
+
+#define EM_NONE 0 // No machine
+#define EM_M32 1 // AT&T WE 32100
+#define EM_SPARC 2 // SPARC
+#define EM_386 3 // Intel 80386
+#define EM_68K 4 // Motorola 68000
+#define EM_88K 5 // Motorola 88000
+#define EM_860 7 // Intel 80860
+#define EM_MIPS 8 // MIPS RS3000
+
+#define EV_NONE 0 // Invalid version
+#define EV_CURRENT 1 // Current version
+
+#define ELF_EXECUTABLE (1 << 0)
+#define ELF_WRITABLE (1 << 1)
+#define ELF_READABLE (1 << 2)
+
+#define Elf32_Addr uint32_t // Unsigned program address
+#define Elf32_Half uint16_t // Unsigned medium integer
+#define Elf32_Off uint32_t // Unsigned file offset
+#define Elf32_Sword uint32_t // Signed large integer
+#define Elf32_Word uint32_t // Unsigned large integer
+
+#define ELF_EXEC (1 << 0)
+#define ELF_WRITE (1 << 1)
+#define ELF_READ (1 << 2)
+
+// ELF header
+typedef struct {
+ unsigned char e_ident[16];
+ Elf32_Half e_type; // Object file type (ET_*)
+ Elf32_Half e_machine; // Required architecture (EM_*)
+ Elf32_Word e_version; // Object file version (EV_*)
+ Elf32_Addr e_entry; // File entry point
+ Elf32_Off e_phoff; // Program header table's offset(bytes)
+ Elf32_Off e_shoff; // Section header table's offset(bytes)
+ Elf32_Word e_flags;
+ Elf32_Half e_ehsize; // ELF Header size
+ Elf32_Half
+ e_phentsize; // Size of program's header tables(all are the same size)
+ Elf32_Half e_phnum; // Amount of program headers
+ Elf32_Half e_shentsize;
+ Elf32_Half e_shnum;
+ Elf32_Half e_shstrndx;
+} __attribute__((packed)) ELFHeader;
+
+// Section header
+typedef struct {
+ Elf32_Word sh_name;
+ Elf32_Word sh_type;
+ Elf32_Word sh_flags;
+ Elf32_Addr sh_addr;
+ Elf32_Off sh_offset;
+ Elf32_Word sh_size;
+ Elf32_Word sh_link;
+ Elf32_Word sh_info;
+ Elf32_Word sh_addralign;
+ Elf32_Word sh_entsize;
+} Elf32_Shdr;
+
+enum ShT_Types {
+ SHT_NULL = 0, // Null section
+ SHT_PROGBITS = 1, // Program information
+ SHT_SYMTAB = 2, // Symbol table
+ SHT_STRTAB = 3, // String table
+ SHT_RELA = 4, // Relocation (w/ addend)
+ SHT_NOBITS = 8, // Not present in file
+ SHT_REL = 9, // Relocation (no addend)
+};
+
+// Program header
+typedef struct {
+ Elf32_Word p_type;
+ Elf32_Off p_offset;
+ Elf32_Addr p_vaddr;
+ Elf32_Addr p_paddr;
+ Elf32_Word p_filesz;
+ Elf32_Word p_memsz;
+ Elf32_Word p_flags;
+ Elf32_Word p_align;
+} __attribute__((packed)) Elf32_Phdr;
+
+
+void *load_elf_file(const char *f, uint32_t *ds);
+#endif
diff --git a/fs/devfs.c b/fs/devfs.c
new file mode 100644
index 0000000..14748a7
--- /dev/null
+++ b/fs/devfs.c
@@ -0,0 +1,91 @@
+#include <drivers/keyboard.h>
+#include <drivers/serial.h>
+#include <fs/devfs.h>
+#include <fs/vfs.h>
+#include <random.h>
+
+devfs_file files[20];
+int num_files = 0;
+
+vfs_inode_t *devfs_add_file(
+ char *path,
+ int (*read)(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd),
+ int (*write)(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd),
+ vfs_vm_object_t *(get_vm_object)(uint64_t length, uint64_t offset,
+ vfs_fd_t *fd),
+ uint8_t has_data, uint8_t can_write, int type) {
+ files[num_files].name = copy_and_allocate_string(path);
+
+ vfs_inode_t *i = kmalloc(sizeof(vfs_inode_t));
+ files[num_files].inode = i;
+ i->type = type;
+ i->read = read;
+ i->write = write;
+ i->close = NULL;
+ i->get_vm_object = get_vm_object;
+ i->has_data = has_data;
+ i->is_open = 1;
+ i->can_write = can_write;
+ num_files++;
+ return i;
+}
+
+vfs_inode_t *devfs_open(const char *file) {
+ for (int i = 0; i < num_files; i++)
+ if (isequal_n(files[i].name, file, strlen(files[i].name)))
+ return files[i].inode;
+
+ return 0;
+}
+
+int devfs_read(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd) {
+ return fd->inode->read(buffer, offset, len, fd);
+}
+
+int devfs_write(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd) {
+ return fd->inode->write(buffer, offset, len, fd);
+}
+
+vfs_vm_object_t *devfs_get_vm_object(uint64_t length, uint64_t offset,
+ vfs_fd_t *fd) {
+ return fd->inode->get_vm_object(length, offset, fd);
+}
+
+int stdout_write(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd) {
+ (void)offset;
+ (void)fd;
+
+ int rc = len;
+ for (; len--;)
+ putc(*buffer++);
+ return rc;
+}
+
+int serial_write(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd) {
+ (void)offset;
+ (void)fd;
+
+ int rc = len;
+ for (; len--;)
+ write_serial(*buffer++);
+ return rc;
+}
+
+void add_serial(void) {
+ devfs_add_file("/serial", NULL, serial_write, NULL, 0, 1,
+ FS_TYPE_CHAR_DEVICE);
+}
+
+void add_stdout(void) {
+ devfs_add_file("/stdout", NULL, stdout_write, NULL, 0, 1,
+ FS_TYPE_CHAR_DEVICE);
+}
+
+vfs_inode_t *devfs_mount(void) {
+ vfs_inode_t *root = kmalloc_eternal(sizeof(vfs_inode_t));
+ root->open = devfs_open;
+ root->read = devfs_read;
+ root->write = devfs_write;
+ root->close = NULL;
+ return root;
+}
diff --git a/fs/devfs.h b/fs/devfs.h
new file mode 100644
index 0000000..23a499e
--- /dev/null
+++ b/fs/devfs.h
@@ -0,0 +1,26 @@
+#ifndef DEVFS_H
+#define DEVFS_H
+#include <defs.h>
+#include <fs/vfs.h>
+#include <stdint.h>
+
+typedef struct devfs_file {
+ char *name;
+ vfs_inode_t *inode;
+} devfs_file;
+
+vfs_inode_t *devfs_mount(void);
+vfs_inode_t *devfs_open(const char *file);
+int devfs_read(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd);
+int devfs_write(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd);
+void add_stdout(void);
+void add_serial(void);
+vfs_inode_t *devfs_add_file(
+ char *path,
+ int (*read)(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd),
+ int (*write)(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd),
+ vfs_vm_object_t *(*get_vm_object)(uint64_t length, uint64_t offset,
+ vfs_fd_t *fd),
+ uint8_t has_data, uint8_t can_write, int type);
+
+#endif
diff --git a/fs/ext2.c b/fs/ext2.c
new file mode 100644
index 0000000..3b4dba8
--- /dev/null
+++ b/fs/ext2.c
@@ -0,0 +1,633 @@
+#include <assert.h>
+#include <fs/ext2.h>
+#include <fs/vfs.h>
+#include <stdint.h>
+#include <string.h>
+
+#define EXT2_SUPERBLOCK_SECTOR 2
+#define EXT2_ROOT_INODE 2
+
+#define BLOCKS_REQUIRED(_a, _b) ((_a) / (_b) + (((_a) % (_b)) != 0))
+
+superblock_t *superblock;
+uint32_t block_byte_size;
+uint32_t inode_size;
+uint32_t inodes_per_block;
+
+#define BLOCK_SIZE (block_byte_size)
+
+void ext2_close(vfs_fd_t *fd) {
+ return; // There is nothing to clear
+}
+
+int read_inode(int inode_num, unsigned char *data, uint64_t size,
+ uint64_t offset, uint64_t *file_size);
+
+void ext2_read_block(uint32_t block, void *address, size_t size,
+ size_t offset) {
+ read_lba(block * block_byte_size / 512, address, size, offset);
+}
+
+void ext2_write_block(uint32_t block, void *address, size_t size,
+ size_t offset) {
+ write_lba(block * block_byte_size / 512, address, size, offset);
+}
+
+void write_group_descriptor(uint32_t group_index, bgdt_t *block_group) {
+ int starting_block = (1024 == block_byte_size) ? 2 : 1;
+ ext2_write_block(starting_block, block_group, sizeof(bgdt_t),
+ group_index * sizeof(bgdt_t));
+}
+
+void get_group_descriptor(uint32_t group_index, bgdt_t *block_group) {
+ int starting_block = (1024 == block_byte_size) ? 2 : 1;
+ ext2_read_block(starting_block, block_group, sizeof(bgdt_t),
+ group_index * sizeof(bgdt_t));
+}
+
+uint32_t num_block_groups(void) {
+ // Determining the Number of Block Groups
+
+ // From the Superblock, extract the size of each block, the total
+ // number of inodes, the total number of blocks, the number of blocks
+ // per block group, and the number of inodes in each block group. From
+ // this information we can infer the number of block groups there are
+ // by:
+
+ // Rounding up the total number of blocks divided by the number of
+ // blocks per block group
+ uint32_t num_blocks = superblock->num_blocks;
+ uint32_t num_blocks_in_group = superblock->num_blocks_in_group;
+ uint32_t b = num_blocks / num_blocks_in_group;
+ if (num_blocks % num_blocks_in_group != 0)
+ b++;
+
+ // Rounding up the total number of inodes divided by the number of
+ // inodes per block group
+ uint32_t num_inodes = superblock->num_inodes;
+ uint32_t num_inodes_in_group = superblock->num_inodes_in_group;
+ uint32_t i = num_inodes / num_inodes_in_group;
+ if (num_inodes % num_inodes_in_group != 0)
+ i++;
+ // Both (and check them against each other)
+ assert(i == b);
+ return i;
+}
+
+void ext2_block_containing_inode(uint32_t inode_index, uint32_t *block_index,
+ uint32_t *offset) {
+ assert(0 != inode_index);
+ bgdt_t block_group;
+ get_group_descriptor((inode_index - 1) / superblock->num_inodes_in_group,
+ &block_group);
+
+ uint64_t full_offset =
+ ((inode_index - 1) % superblock->num_inodes_in_group) * inode_size;
+ *block_index = block_group.starting_inode_table +
+ (full_offset >> (superblock->block_size + 10));
+ *offset = full_offset & (block_byte_size - 1);
+}
+
+void ext2_get_inode_header(int inode_index, inode_t *data) {
+ uint32_t block_index;
+ uint32_t block_offset;
+ ext2_block_containing_inode(inode_index, &block_index, &block_offset);
+
+ uint8_t mem_block[inode_size];
+ ext2_read_block(block_index, mem_block, inode_size, block_offset);
+
+ memcpy(data, mem_block, inode_size);
+}
+
+void ext2_write_inode(int inode_index, inode_t *data) {
+ uint32_t block_index;
+ uint32_t block_offset;
+ ext2_block_containing_inode(inode_index, &block_index, &block_offset);
+
+ uint8_t mem_block[inode_size];
+ memcpy(mem_block, data, inode_size);
+ ext2_write_block(block_index, mem_block, inode_size, block_offset);
+}
+
+int ext2_get_inode_in_directory(int dir_inode, char *file,
+ direntry_header_t *entry) {
+ // FIXME: Allocate sufficent size each time
+ unsigned char *data = kmalloc(block_byte_size * 5);
+ ASSERT_BUT_FIXME_PROPOGATE(
+ -1 != read_inode(dir_inode, data, block_byte_size * 5, 0, 0));
+
+ direntry_header_t *dir;
+ unsigned char *data_p = data;
+ for (; (dir = (direntry_header_t *)data_p)->inode; data_p += dir->size) {
+ if (0 == dir->size)
+ break;
+ if (0 == dir->name_length)
+ continue;
+ if (0 ==
+ memcmp(data_p + sizeof(direntry_header_t), file, dir->name_length)) {
+ if (strlen(file) > dir->name_length)
+ continue;
+ if (entry)
+ memcpy(entry, data_p, sizeof(direntry_header_t));
+ return dir->inode;
+ }
+ }
+ return 0;
+}
+
+int ext2_read_dir(int dir_inode, unsigned char *buffer, size_t len,
+ size_t offset) {
+ unsigned char data[block_byte_size];
+ read_inode(dir_inode, data, block_byte_size, 0, 0);
+
+ direntry_header_t *dir;
+ struct dirent tmp_entry;
+ size_t n_dir = 0;
+ int rc = 0;
+ unsigned char *data_p = data;
+ for (; (dir = (direntry_header_t *)data_p)->inode && len > 0;
+ data_p += dir->size, n_dir++) {
+ if (0 == dir->size)
+ break;
+ if (0 == dir->name_length)
+ continue;
+ if (n_dir < (offset / sizeof(struct dirent)))
+ continue;
+
+ memcpy(tmp_entry.d_name, data_p + sizeof(direntry_header_t),
+ dir->name_length);
+ tmp_entry.d_name[dir->name_length] = '\0';
+ uint8_t *p = (uint8_t *)&tmp_entry;
+ size_t l = sizeof(struct dirent);
+
+ l = (len < l) ? len : l;
+ memcpy(buffer, p, l);
+ len -= l;
+ rc += l;
+ }
+ return rc;
+}
+
+uint32_t ext2_find_inode(const char *file) {
+ int cur_path_inode = EXT2_ROOT_INODE;
+
+ if (*file == '/' && *(file + 1) == '\0')
+ return cur_path_inode;
+
+ char *str = copy_and_allocate_string(file);
+ char *orig_str = str;
+
+ char *start;
+ for (;;) {
+ int final = 0;
+ start = str + 1;
+ str++;
+
+ for (; '/' != *str && '\0' != *str; str++)
+ ;
+ if ('\0' == *str)
+ final = 1;
+
+ *str = '\0';
+
+ direntry_header_t a;
+ if (0 == (cur_path_inode =
+ ext2_get_inode_in_directory(cur_path_inode, start, &a))) {
+ kfree(orig_str);
+ return 0;
+ }
+
+ if (final)
+ break;
+
+ // The expected returned entry is a directory
+ if (TYPE_INDICATOR_DIRECTORY != a.type_indicator) {
+ kfree(orig_str);
+ kprintf("FAILED\n");
+ return 0;
+ }
+ }
+ kfree(orig_str);
+ return cur_path_inode;
+}
+
+uint32_t get_singly_block_index(uint32_t singly_block_ptr, uint32_t i) {
+ uint8_t block[block_byte_size];
+ ext2_read_block(singly_block_ptr, block, block_byte_size, 0);
+ uint32_t index = *(uint32_t *)(block + (i * (32 / 8)));
+ return index;
+}
+
+int get_block(inode_t *inode, uint32_t i) {
+ if (i < 12)
+ return inode->block_pointers[i];
+
+ i -= 12;
+ uint32_t singly_block_size = block_byte_size / (32 / 8);
+ uint32_t double_block_size = (singly_block_size * singly_block_size);
+ if (i < singly_block_size) {
+ return get_singly_block_index(inode->single_indirect_block_pointer, i);
+ } else if (i < double_block_size) {
+ i -= singly_block_size;
+ uint32_t singly_entry = get_singly_block_index(
+ inode->double_indirect_block_pointer, i / singly_block_size);
+ uint32_t offset_in_entry = i % singly_block_size;
+ int block = get_singly_block_index(singly_entry, offset_in_entry);
+ return block;
+ }
+ assert(0);
+ return 0;
+}
+
+int get_free_block(int allocate) {
+ bgdt_t block_group;
+ uint8_t bitmap[BLOCK_SIZE];
+ assert(0 < superblock->num_blocks_unallocated);
+ for (uint32_t g = 0; g < num_block_groups(); g++) {
+ get_group_descriptor(g, &block_group);
+
+ if (block_group.num_unallocated_blocks_in_group == 0) {
+ kprintf("skip\n");
+ continue;
+ }
+
+ ext2_read_block(block_group.block_usage_bitmap, bitmap, BLOCK_SIZE, 0);
+ for (uint32_t i = 0; i < superblock->num_blocks_in_group; i++) {
+ if (!(bitmap[i >> 3] & (1 << (i % 8)))) {
+ if (allocate) {
+ bitmap[i >> 3] |= (1 << (i % 8));
+ ext2_write_block(block_group.block_usage_bitmap, bitmap, BLOCK_SIZE,
+ 0);
+ block_group.num_unallocated_blocks_in_group--;
+ write_group_descriptor(g, &block_group);
+ superblock->num_blocks_unallocated--;
+ write_lba(EXT2_SUPERBLOCK_SECTOR, (void *)superblock, 2 * SECTOR_SIZE,
+ 0);
+ }
+ return i + g * superblock->num_blocks_in_group + 1;
+ }
+ }
+ }
+ return -1;
+}
+
+int get_free_inode(int allocate) {
+ bgdt_t block_group;
+ assert(0 < superblock->num_inodes_unallocated);
+ for (uint32_t g = 0; g < num_block_groups(); g++) {
+ get_group_descriptor(g, &block_group);
+
+ if (0 == block_group.num_unallocated_inodes_in_group)
+ continue;
+
+ uint8_t bitmap[BLOCK_SIZE];
+ ext2_read_block(block_group.inode_usage_bitmap, bitmap, BLOCK_SIZE, 0);
+ for (uint32_t i = 0; i < superblock->num_inodes_in_group; i++) {
+ if (!(bitmap[i / 8] & (1 << (i % 8)))) {
+ if (allocate) {
+ bitmap[i / 8] |= (1 << (i % 8));
+ ext2_write_block(block_group.inode_usage_bitmap, bitmap, BLOCK_SIZE,
+ 0);
+ block_group.num_unallocated_inodes_in_group--;
+ write_group_descriptor(g, &block_group);
+ superblock->num_inodes_unallocated--;
+ write_lba(EXT2_SUPERBLOCK_SECTOR, (void *)superblock, 2 * SECTOR_SIZE,
+ 0);
+ }
+ return i + g * superblock->num_inodes_in_group + 1;
+ }
+ }
+ }
+ return -1;
+}
+
+int write_inode(int inode_num, unsigned char *data, uint64_t size,
+ uint64_t offset, uint64_t *file_size, int append) {
+ (void)file_size;
+ uint8_t inode_buffer[inode_size];
+ ext2_get_inode_header(inode_num, (inode_t *)inode_buffer);
+ inode_t *inode = (inode_t *)inode_buffer;
+
+ uint64_t fsize = (uint64_t)(((uint64_t)inode->_upper_32size << 32) |
+ (uint64_t)inode->low_32size);
+ if (append)
+ offset = fsize;
+
+ uint32_t block_start = offset / block_byte_size;
+ uint32_t block_offset = offset % block_byte_size;
+
+ int num_blocks_used = inode->num_disk_sectors / (BLOCK_SIZE / SECTOR_SIZE);
+
+ if (size + offset > fsize)
+ fsize = size + offset;
+
+ int num_blocks_required = BLOCKS_REQUIRED(fsize, BLOCK_SIZE);
+
+ for (int i = num_blocks_used; i < num_blocks_required; i++) {
+ if (i > 12)
+ assert(0);
+ int b = get_free_block(1 /*true*/);
+ assert(-1 != b);
+ inode->block_pointers[i] = b;
+ }
+
+ inode->num_disk_sectors = num_blocks_required * (BLOCK_SIZE / SECTOR_SIZE);
+
+ int bytes_written = 0;
+ for (int i = block_start; size; i++) {
+ uint32_t block = get_block(inode, i);
+ if (0 == block) {
+ kprintf("block_not_found\n");
+ break;
+ }
+
+ int write_len = ((size + block_offset) > block_byte_size)
+ ? (block_byte_size - block_offset)
+ : size;
+ ext2_write_block(block, data + bytes_written, write_len, block_offset);
+ block_offset = 0;
+ bytes_written += write_len;
+ size -= write_len;
+ }
+ inode->low_32size = fsize;
+ inode->_upper_32size = (fsize >> 32);
+ ext2_write_inode(inode_num, inode);
+ return bytes_written;
+}
+
+int read_inode(int inode_num, unsigned char *data, uint64_t size,
+ uint64_t offset, uint64_t *file_size) {
+ // TODO: Fail if size is lower than the size of the file being read, and
+ // return the size of the file the callers is trying to read.
+ uint8_t inode_buffer[inode_size];
+ ext2_get_inode_header(inode_num, (inode_t *)inode_buffer);
+ inode_t *inode = (inode_t *)inode_buffer;
+
+ uint64_t fsize = (uint64_t)(((uint64_t)inode->_upper_32size << 32) |
+ (uint64_t)inode->low_32size);
+
+ if (file_size)
+ *file_size = fsize;
+
+ if (size > fsize - offset)
+ size -= ((size + offset) - fsize);
+
+ if (size == 0)
+ return 0;
+
+ if (offset > fsize)
+ return 0;
+
+ uint32_t block_start = offset / block_byte_size;
+ uint32_t block_offset = offset % block_byte_size;
+
+ int bytes_read = 0;
+ for (int i = block_start; size; i++) {
+ uint32_t block = get_block(inode, i);
+ if (0 == block) {
+ klog("Filesystem EXT2: Unable to find block", LOG_WARN);
+ return -1;
+ }
+
+ int read_len = ((size + block_offset) > block_byte_size)
+ ? (block_byte_size - block_offset)
+ : size;
+ ext2_read_block(block, data + bytes_read, read_len, block_offset);
+ block_offset = 0;
+ bytes_read += read_len;
+ size -= read_len;
+ }
+ return bytes_read;
+}
+
+size_t ext2_read_file_offset(const char *file, unsigned char *data,
+ uint64_t size, uint64_t offset,
+ uint64_t *file_size) {
+ // TODO: Fail if the file does not exist.
+ uint32_t inode = ext2_find_inode(file);
+ return read_inode(inode, data, size, offset, file_size);
+}
+
+size_t ext2_read_file(const char *file, unsigned char *data, size_t size,
+ uint64_t *file_size) {
+ return ext2_read_file_offset(file, data, size, 0, file_size);
+}
+
+int resolve_link(int inode_num) {
+ uint8_t tmp[inode_size];
+ inode_t *inode = (inode_t *)tmp;
+ uint64_t inode_size =
+ (((uint64_t)inode->_upper_32size) << 32) & inode->low_32size;
+ assert(inode_size <= 60);
+ ext2_get_inode_header(inode_num, inode);
+ char *path = (char *)(tmp + (10 * 4));
+ path--;
+ *path = '/';
+ return ext2_find_inode(path);
+}
+
+int ext2_write(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd) {
+ uint64_t file_size;
+ int rc;
+ int inode_num = fd->inode->inode_num;
+ assert(fd->inode->type != FS_TYPE_DIRECTORY);
+ if (fd->inode->type == FS_TYPE_LINK) {
+ inode_num = resolve_link(inode_num);
+ }
+ rc = write_inode(inode_num, buffer, len, offset, &file_size, 0);
+ return rc;
+}
+
+int ext2_read(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd) {
+ uint64_t file_size;
+ int rc;
+ int inode_num = fd->inode->inode_num;
+ if (fd->inode->type == FS_TYPE_DIRECTORY) {
+ rc = ext2_read_dir(inode_num, buffer, len, offset);
+ return rc;
+ }
+ if (fd->inode->type == FS_TYPE_LINK) {
+ inode_num = resolve_link(inode_num);
+ }
+ rc = read_inode(inode_num, buffer, len, offset, &file_size);
+ return rc;
+}
+
+vfs_inode_t *ext2_open(const char *path) {
+ uint32_t inode_num = ext2_find_inode(path);
+ if (0 == inode_num)
+ return NULL;
+
+ inode_t ext2_inode[inode_size];
+ ext2_get_inode_header(inode_num, ext2_inode);
+ uint64_t file_size =
+ ((uint64_t)(ext2_inode->_upper_32size) << 32) | ext2_inode->low_32size;
+
+ uint8_t type;
+ switch ((ext2_inode->types_permissions / 0x1000)) {
+ case 0xA:
+ type = FS_TYPE_LINK;
+ break;
+ case 0x4:
+ type = FS_TYPE_DIRECTORY;
+ break;
+ default:
+ type = FS_TYPE_FILE;
+ break;
+ }
+
+ return vfs_create_inode(inode_num, type, 1 /*has_data*/, 1 /*can_write*/,
+ 1 /*is_open*/, NULL /*internal_object*/, file_size,
+ ext2_open, ext2_create_file, ext2_read, ext2_write,
+ ext2_close, NULL /*get_vm_object*/);
+}
+
+uint64_t end_of_last_entry_position(int dir_inode, uint64_t *entry_offset,
+ direntry_header_t *meta) {
+ // FIXME: Allocate sufficent size each time
+ unsigned char data[block_byte_size * 5];
+ uint64_t file_size = 0;
+ read_inode(dir_inode, data, block_byte_size * 5, 0, &file_size);
+ assert(block_byte_size * 5 > file_size);
+
+ direntry_header_t *dir;
+ unsigned char *data_p = data;
+ uint64_t pos = 0;
+ uint64_t prev = pos;
+ for (; pos < file_size && (dir = (direntry_header_t *)data_p)->size;
+ data_p += dir->size, prev = pos, pos += dir->size)
+ ;
+ if (entry_offset)
+ *entry_offset = prev;
+ if (meta)
+ memcpy(meta, ((char *)data) + prev, sizeof(direntry_header_t));
+ return pos;
+}
+
+int ext2_create_entry(const char *path, int mode, int *error) {
+ (void)mode;
+ *error = 0;
+ // Check if the file already exists
+ {
+ uint32_t inode_num = ext2_find_inode(path);
+ if (0 != inode_num) {
+ klog("ext2_create_file: File already exists", LOG_WARN);
+ *error = 1;
+ return inode_num;
+ }
+ }
+
+ uint32_t parent_inode;
+ // Get the parent directory
+ char path_buffer[strlen(path) + 1];
+ strcpy(path_buffer, path);
+ char *e = path_buffer;
+ for (; *e; e++)
+ ;
+ for (; *e != '/'; e--)
+ ;
+ *e = '\0';
+ if (*path_buffer == '\0') {
+ parent_inode = EXT2_ROOT_INODE;
+ } else {
+ parent_inode = ext2_find_inode(path_buffer);
+ }
+ if (0 == parent_inode) { // Parent does not exist
+ klog("ext2_create_file: Parent does not exist", LOG_WARN);
+ *error = 1;
+ return -1;
+ }
+
+ const char *filename = e + 1;
+
+ int new_file_inode = get_free_inode(1);
+ if (-1 == new_file_inode) {
+ klog("ext2_create_file: Unable to find free inode", LOG_WARN);
+ *error = 1;
+ return -1;
+ }
+ assert(0 != new_file_inode);
+
+ uint64_t entry_offset = 0;
+ direntry_header_t meta;
+ end_of_last_entry_position(parent_inode, &entry_offset, &meta);
+
+ uint32_t padding_in_use = block_byte_size - entry_offset;
+
+ kprintf("meta.size: %x\n", meta.size);
+ kprintf("padding_in_use: %x\n", padding_in_use);
+ // assert(padding_in_use == meta.size);
+ assert(padding_in_use >= (sizeof(direntry_header_t) + strlen(filename)));
+
+ // Modify the entry to have its real size
+ meta.size = sizeof(direntry_header_t) + meta.name_length;
+ meta.size += (4 - (meta.size % 4));
+ write_inode(parent_inode, (unsigned char *)&meta, sizeof(direntry_header_t),
+ entry_offset, NULL, 0);
+
+ // Create new entry
+ uint32_t new_entry_offset = entry_offset + meta.size;
+ direntry_header_t entry;
+ entry.inode = new_file_inode;
+ entry.type_indicator = TYPE_INDICATOR_REGULAR;
+ entry.name_length = strlen(filename);
+ entry.size = (sizeof(direntry_header_t) + entry.name_length);
+ entry.size += (4 - (entry.size % 4));
+
+ uint32_t length_till_next_block = 1024 - (new_entry_offset % 1024);
+ if (0 == length_till_next_block)
+ length_till_next_block = 1024;
+ assert(entry.size < length_till_next_block);
+ entry.size = length_till_next_block;
+
+ uint8_t buffer[entry.size];
+ memset(buffer, 0, entry.size);
+ memcpy(buffer, &entry, sizeof(entry));
+ memcpy(buffer + sizeof(entry), filename, entry.name_length);
+ write_inode(parent_inode, (unsigned char *)buffer, entry.size,
+ new_entry_offset, NULL, 0);
+ return new_file_inode;
+}
+
+int ext2_create_file(const char *path, int mode) {
+ int err;
+ int new_file_inode = ext2_create_entry(path, mode, &err);
+ if (err)
+ return 0;
+ // Create the inode header
+ uint8_t inode_buffer[inode_size];
+ inode_t *new_inode = (inode_t *)inode_buffer;
+ memset(inode_buffer, 0, inode_size);
+ new_inode->types_permissions = 0x8000;
+ new_inode->num_hard_links = 1;
+ ext2_write_inode(new_file_inode, new_inode);
+ return new_file_inode;
+}
+
+vfs_inode_t *ext2_mount(void) {
+ vfs_inode_t *root = kmalloc_eternal(sizeof(vfs_inode_t));
+ root->open = ext2_open;
+ root->read = ext2_read;
+ root->write = ext2_write;
+ root->close = ext2_close;
+ root->create_file = ext2_create_file;
+ parse_superblock();
+ return root;
+}
+
+void parse_superblock(void) {
+ superblock = ksbrk(2 * SECTOR_SIZE);
+ read_lba(EXT2_SUPERBLOCK_SECTOR, (void *)superblock, 2 * SECTOR_SIZE, 0);
+ block_byte_size = 1024 << superblock->block_size;
+
+ if (0xEF53 != superblock->ext2_signature) {
+ klog("Incorrect ext2 signature in superblock.", LOG_ERROR);
+ for (;;)
+ ; // TODO: Fail properly
+ }
+
+ if (1 <= superblock->major_version)
+ inode_size = ((ext_superblock_t *)superblock)->inode_size;
+
+ inodes_per_block = block_byte_size / inode_size;
+}
diff --git a/fs/ext2.h b/fs/ext2.h
new file mode 100644
index 0000000..63684da
--- /dev/null
+++ b/fs/ext2.h
@@ -0,0 +1,139 @@
+#ifndef EXT2_H
+#define EXT2_H
+#include <drivers/ata.h>
+#include <fs/vfs.h>
+#include <kmalloc.h>
+#include <stdint.h>
+
+typedef struct Superblock {
+ uint32_t num_inodes;
+ uint32_t num_blocks;
+ uint32_t num_blocks_reserved;
+ uint32_t num_blocks_unallocated;
+ uint32_t num_inodes_unallocated;
+ uint32_t superblock_block_num;
+ uint32_t block_size;
+ uint32_t fragment_size;
+ uint32_t num_blocks_in_group;
+ uint32_t num_fragments_in_group;
+ uint32_t num_inodes_in_group;
+ uint32_t last_mount;
+ uint32_t last_write;
+ uint16_t num_mounts_since_fsck;
+ uint16_t num_mounts_allowed;
+ uint16_t ext2_signature; // 0xEF53
+ uint16_t fs_state;
+ uint16_t when_error;
+ uint16_t minor_version;
+ uint32_t last_fsck;
+ uint32_t interval_fsck;
+ uint32_t os_id;
+ uint32_t major_version;
+ uint16_t userid_reserved_blocks;
+ uint16_t groupid_reserved_blocks;
+} __attribute__((packed)) superblock_t;
+
+typedef struct ExtendedSuperblock {
+ uint32_t num_inodes;
+ uint32_t num_blocks;
+ uint32_t num_blocks_reserved;
+ uint32_t num_blocks_unallocated;
+ uint32_t num_inodes_unallocated;
+ uint32_t superblock_block_num;
+ uint32_t block_size;
+ uint32_t fragment_size;
+ uint32_t num_blocks_group;
+ uint32_t num_fragments_group;
+ uint32_t num_inodes_group;
+ uint32_t last_mount;
+ uint32_t last_write;
+ uint16_t num_mounts_since_fsck;
+ uint16_t num_mounts_allowed;
+ uint16_t ext2_signature; // 0xEF53
+ uint16_t fs_state;
+ uint16_t when_error;
+ uint16_t minor_version;
+ uint32_t last_fsck;
+ uint32_t interval_fsck;
+ uint32_t os_id;
+ uint32_t major_version;
+ uint16_t userid_reserved_blocks;
+ uint16_t groupid_reserved_blocks;
+ uint32_t pad;
+ uint16_t inode_size;
+} __attribute__((packed)) ext_superblock_t;
+
+typedef struct BlockGroupDescriptorTable {
+ uint32_t block_usage_bitmap;
+ uint32_t inode_usage_bitmap;
+ uint32_t starting_inode_table;
+ uint16_t num_unallocated_blocks_in_group;
+ uint16_t num_unallocated_inodes_in_group;
+ uint16_t num_directories_group;
+} __attribute__((packed)) bgdt_t;
+
+typedef struct INode {
+ uint16_t types_permissions;
+ uint16_t user_id;
+ uint32_t low_32size;
+ uint32_t last_access_time;
+ uint32_t creation_time;
+ uint32_t last_modification_time;
+ uint32_t deletion_time;
+ uint16_t group_id;
+ uint16_t num_hard_links;
+ uint32_t num_disk_sectors;
+ uint32_t flags;
+ uint32_t os_specific;
+ uint32_t block_pointers[12];
+ uint32_t single_indirect_block_pointer;
+ uint32_t double_indirect_block_pointer;
+ uint32_t triple_indirect_block_pointer;
+ uint32_t gen_number;
+ uint32_t _extended_attribute_block;
+ uint32_t _upper_32size;
+ uint32_t address_fragment;
+ uint32_t os_specific2;
+} __attribute__((packed)) inode_t;
+
+// 0 Unknown type
+// 1 Regular file
+// 2 Directory
+// 3 Character device
+// 4 Block device
+// 5 FIFO
+// 6 Socket
+// 7 Symbolic link (soft link)
+#define TYPE_INDICATOR_UNKOWN 0
+#define TYPE_INDICATOR_REGULAR 1
+#define TYPE_INDICATOR_DIRECTORY 2
+#define TYPE_INDICATOR_CHARACTER_DEVICE 3
+#define TYPE_INDICATOR_BLOCK_DEVICE 4
+#define TYPE_INDICATOR_FIFO 5
+#define TYPE_INDICATOR_SOCKET 6
+#define TYPE_INDICATOR_SOFT_LINK 7
+
+#define FIFO 0x1000
+#define CHARACTER_DEVICE 0x2000
+#define DIRECTORY 0x4000
+#define BLOCK_DEVICE 0x6000
+#define REGULAR_FILE 0x8000
+#define SYMBOLIC_LINK 0xA000
+#define UNIX_SOCKET 0xC000
+
+typedef struct DirectoryEntryHeader {
+ uint32_t inode;
+ uint16_t size;
+ uint8_t name_length;
+ uint8_t type_indicator;
+} __attribute__((packed)) direntry_header_t;
+
+int ext2_create_file(const char *path, int mode);
+vfs_inode_t *ext2_mount(void);
+void parse_superblock(void);
+size_t ext2_read_file_offset(const char *file, unsigned char *data,
+ uint64_t size, uint64_t offset,
+ uint64_t *file_size);
+size_t ext2_read_file(const char *file, unsigned char *data, size_t size,
+ uint64_t *file_size);
+#endif
diff --git a/fs/fifo.c b/fs/fifo.c
new file mode 100644
index 0000000..d515ed7
--- /dev/null
+++ b/fs/fifo.c
@@ -0,0 +1,97 @@
+#include "fifo.h"
+#include <errno.h>
+
+#define STARTING_SIZE 4096
+
+void fifo_close(vfs_fd_t *fd) {
+ // TODO: Implement
+ (void)fd;
+ return;
+}
+
+int fifo_object_write(uint8_t *buffer, uint64_t offset, uint64_t len,
+ FIFO_FILE *file) {
+ (void)offset;
+ file->has_data = 1;
+ if (file->write_len + len >= file->buffer_len) {
+ file->can_write = 0;
+ return -EAGAIN;
+ }
+ memcpy(file->buffer + file->write_len, buffer, len);
+ file->write_len += len;
+ return len;
+}
+
+int fifo_object_read(uint8_t *buffer, uint64_t offset, uint64_t len,
+ FIFO_FILE *file) {
+ (void)offset;
+ if (file->write_len == 0) {
+ file->has_data = 0;
+ return -EAGAIN;
+ }
+
+ if (len == 0)
+ return 0;
+
+ file->can_write = 1;
+ if (len > file->write_len)
+ len = file->write_len;
+
+ memcpy(buffer, file->buffer, len);
+ // Shift bufffer to the left
+ memcpy(file->buffer, file->buffer + len, file->buffer_len - len);
+
+ file->write_len -= len;
+ if (file->write_len == 0) {
+ file->has_data = 0;
+ }
+ return len;
+}
+
+FIFO_FILE *create_fifo_object(void) {
+ FIFO_FILE *n = kmalloc(sizeof(FIFO_FILE));
+ n->buffer = kmalloc(STARTING_SIZE);
+ n->buffer_len = STARTING_SIZE;
+ n->write_len = 0;
+ return n;
+}
+
+int create_fifo(void) {
+
+ int fd_n = 0;
+ for (; get_current_task()->file_descriptors[fd_n]; fd_n++)
+ ;
+
+ vfs_fd_t *fd = kmalloc(sizeof(vfs_fd_t));
+ fd->flags = O_RDWR | O_NONBLOCK;
+ get_current_task()->file_descriptors[fd_n] = fd;
+ fd->inode = kmalloc(sizeof(vfs_inode_t));
+
+ fd->inode->internal_object = (void *)create_fifo_object();
+ fd->inode->open = NULL;
+ fd->inode->read = fifo_read;
+ fd->inode->write = fifo_write;
+ fd->inode->close = fifo_close;
+ fd->inode->get_vm_object = NULL;
+ fd->inode->is_open = 1;
+
+ return fd_n;
+}
+
+int fifo_write(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd) {
+ (void)offset;
+ FIFO_FILE *file = (FIFO_FILE *)fd->inode->internal_object;
+ int rc = fifo_object_write(buffer, offset, len, file);
+ fd->inode->has_data = file->has_data;
+ fd->inode->can_write = file->can_write;
+ return rc;
+}
+
+int fifo_read(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd) {
+ FIFO_FILE *file = (FIFO_FILE *)fd->inode->internal_object;
+ file->is_blocking = !(fd->flags & O_NONBLOCK);
+ int rc = fifo_object_read(buffer, offset, len, file);
+ fd->inode->has_data = file->has_data;
+ fd->inode->can_write = file->can_write;
+ return rc;
+}
diff --git a/fs/fifo.h b/fs/fifo.h
new file mode 100644
index 0000000..ee91ba1
--- /dev/null
+++ b/fs/fifo.h
@@ -0,0 +1,26 @@
+#ifndef FIFO_H
+#define FIFO_H
+#include "vfs.h"
+#include <stddef.h>
+#include <stdint.h>
+
+typedef struct {
+ char *buffer;
+ uint64_t buffer_len;
+ uint64_t write_len;
+ uint8_t is_blocking;
+ uint8_t has_data;
+ uint8_t can_write;
+} FIFO_FILE;
+
+int create_fifo(void);
+FIFO_FILE *create_fifo_object(void);
+int fifo_object_write(uint8_t *buffer, uint64_t offset, uint64_t len,
+ FIFO_FILE *file);
+int fifo_object_read(uint8_t *buffer, uint64_t offset, uint64_t len,
+ FIFO_FILE *file);
+int fifo_write(uint8_t *buffer, uint64_t offset, uint64_t len,
+ vfs_fd_t *fd);
+int fifo_read(uint8_t *buffer, uint64_t offset, uint64_t len,
+ vfs_fd_t *fd);
+#endif
diff --git a/fs/shm.c b/fs/shm.c
new file mode 100644
index 0000000..00f8dfb
--- /dev/null
+++ b/fs/shm.c
@@ -0,0 +1,98 @@
+#include <assert.h>
+#include <errno.h>
+#include <fs/shm.h>
+#include <fs/vfs.h>
+#include <hashmap/hashmap.h>
+#include <mmu.h>
+#include <sched/scheduler.h>
+#include <stddef.h>
+
+HashMap *shared_memory_objects;
+
+void shm_init(void) { shared_memory_objects = hashmap_create(10); }
+
+int shm_write(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd) {
+ vfs_vm_object_t *p = fd->inode->internal_object;
+
+ if (offset > p->size)
+ return -EFBIG;
+
+ if (offset + len > p->size)
+ len = p->size - offset;
+
+ memcpy((void *)((uintptr_t)((uintptr_t)p->virtual_object + offset)), buffer,
+ len);
+ return len;
+}
+
+int shm_read(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd) {
+ vfs_vm_object_t *p = fd->inode->internal_object;
+
+ if (offset > p->size)
+ return -EFBIG;
+
+ if (offset + len > p->size)
+ len = p->size - offset;
+
+ memcpy((void *)buffer,
+ (void *)((uintptr_t)((uintptr_t)p->virtual_object + offset)), len);
+ return len;
+}
+
+vfs_vm_object_t *shm_get_vm_object(uint64_t length, uint64_t offset,
+ vfs_fd_t *fd) {
+ (void)length;
+ (void)offset;
+ vfs_vm_object_t *p = fd->inode->internal_object;
+ return p;
+}
+
+int shm_open(const char *name, int oflag, mode_t mode) {
+ // Try to find or create a new shared memory object.
+ vfs_vm_object_t *internal_object =
+ hashmap_get_entry(shared_memory_objects, name);
+ if (!internal_object) {
+ // if (!(oflag & O_CREAT))
+ // return -EMFILE;
+ internal_object = kmalloc(sizeof(vfs_vm_object_t));
+ internal_object->object = NULL;
+ internal_object->size = 0;
+ hashmap_add_entry(shared_memory_objects, name, internal_object, NULL, 0);
+ }
+
+ vfs_inode_t *inode =
+ vfs_create_inode(0 /*inode_num*/, 0 /*type*/, 1 /*has_data*/,
+ 1 /*can_write*/, 1 /*is_open*/, internal_object,
+ 0 /*file_size*/, NULL /*open*/, NULL /*create_file*/,
+ shm_read, shm_write, NULL /*close*/, shm_get_vm_object);
+
+ vfs_fd_t *fd_ptr;
+ int fd = vfs_create_fd(oflag, mode, inode, &fd_ptr);
+ if (-1 == fd) {
+ kfree(inode);
+ return -EMFILE;
+ }
+ return fd;
+}
+
+int shm_unlink(const char *name) {
+ (void)name;
+ return 0;
+}
+
+int ftruncate(int fildes, uint64_t length) {
+ kprintf("ftruncate: %d\n", length);
+ vfs_fd_t *fd = get_current_task()->file_descriptors[fildes];
+ if (!fd)
+ return -EBADF;
+ vfs_vm_object_t *p = fd->inode->internal_object;
+ p->size = length;
+ p->virtual_object = ksbrk(length);
+ int n = (uintptr_t)align_page((void *)(uint32_t)length) / 0x1000;
+ p->object = kmalloc(sizeof(void *) * n);
+ for (int i = 0; i < n; i++)
+ p->object[i] =
+ (void *)(get_page(p->virtual_object + (i * 0x1000), NULL, 0, 0)->frame *
+ 0x1000);
+ return 0;
+}
diff --git a/fs/shm.h b/fs/shm.h
new file mode 100644
index 0000000..fbbdb5c
--- /dev/null
+++ b/fs/shm.h
@@ -0,0 +1,13 @@
+#ifndef SHM_H
+#define SHM_H
+#include <stddef.h>
+#include <stdint.h>
+
+typedef int mode_t;
+
+void shm_init(void);
+int shm_open(const char *name, int oflag, mode_t mode);
+int shm_unlink(const char *name);
+int ftruncate(int fildes, uint64_t length);
+
+#endif
diff --git a/fs/tmpfs.c b/fs/tmpfs.c
new file mode 100644
index 0000000..2c5974b
--- /dev/null
+++ b/fs/tmpfs.c
@@ -0,0 +1,94 @@
+#include <assert.h>
+#include <errno.h>
+#include <fs/fifo.h>
+#include <fs/tmpfs.h>
+#include <halts.h>
+#include <sched/scheduler.h>
+#include <stdint.h>
+
+void tmp_close(vfs_fd_t *fd) {
+ fd->inode->is_open = 0;
+ ((tmp_inode *)fd->inode->internal_object)->read_inode->is_open = 0;
+}
+
+int tmp_write(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd) {
+ tmp_inode *calling_file = fd->inode->internal_object;
+ tmp_inode *child_file = calling_file->read_inode->internal_object;
+ if (child_file->is_closed)
+ return -EPIPE;
+
+ int rc = fifo_object_write(buffer, offset, len, child_file->fifo);
+ calling_file->read_inode->has_data = child_file->fifo->has_data;
+ fd->inode->can_write = child_file->fifo->can_write;
+ return rc;
+}
+
+int tmp_read(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd) {
+ tmp_inode *calling_file = fd->inode->internal_object;
+ tmp_inode *child_file = calling_file->read_inode->internal_object;
+ if (calling_file->is_closed)
+ return -EPIPE;
+
+ int rc = fifo_object_read(buffer, offset, len, calling_file->fifo);
+ fd->inode->has_data = calling_file->fifo->has_data;
+ calling_file->read_inode->can_write = child_file->fifo->can_write;
+ return rc;
+}
+
+void dual_pipe(int fd[2]) {
+ for (int i = 0; i < 2; i++) {
+ tmp_inode *pipe = kmalloc(sizeof(tmp_inode));
+ pipe->fifo = create_fifo_object();
+
+ int has_data = 0;
+ int can_write = 1;
+ int is_open = 1;
+ void *internal_object = pipe;
+ vfs_inode_t *inode = vfs_create_inode(
+ 0 /*inode_num*/, 0 /*type*/, has_data, can_write, is_open,
+ internal_object, 0 /*file_size*/, NULL /*open*/, NULL /*create_file*/,
+ tmp_read, tmp_write, tmp_close, NULL /*get_vm_object*/);
+ assert(inode);
+
+ vfs_fd_t *fd_ptr;
+ fd[i] = vfs_create_fd(O_RDWR | O_NONBLOCK, 0, inode, &fd_ptr);
+ assert(-1 != fd[i]);
+ }
+ vfs_inode_t *f_inode = get_current_task()->file_descriptors[fd[0]]->inode;
+ vfs_inode_t *s_inode = get_current_task()->file_descriptors[fd[1]]->inode;
+ tmp_inode *f_pipe = f_inode->internal_object;
+ tmp_inode *s_pipe = s_inode->internal_object;
+ f_pipe->read_inode = s_inode;
+ s_pipe->read_inode = f_inode;
+ f_pipe->is_closed = 0;
+ s_pipe->is_closed = 0;
+}
+
+void pipe(int fd[2]) {
+ for (int i = 0; i < 2; i++) {
+ tmp_inode *pipe = kmalloc(sizeof(tmp_inode));
+ pipe->fifo = create_fifo_object();
+
+ int has_data = 0;
+ int can_write = 1;
+ int is_open = 1;
+ void *internal_object = pipe;
+ vfs_inode_t *inode = vfs_create_inode(
+ 0 /*inode_num*/, 0 /*type*/, has_data, can_write, is_open,
+ internal_object, 0 /*file_size*/, NULL /*open*/, NULL /*create_file*/,
+ tmp_read, tmp_write, tmp_close, NULL /*get_vm_object*/);
+ assert(inode);
+
+ vfs_fd_t *fd_ptr;
+ fd[i] = vfs_create_fd(O_RDWR, 0, inode, &fd_ptr);
+ assert(-1 != fd[i]);
+ }
+ vfs_inode_t *f_inode = get_current_task()->file_descriptors[fd[0]]->inode;
+ vfs_inode_t *s_inode = get_current_task()->file_descriptors[fd[1]]->inode;
+ tmp_inode *f_pipe = f_inode->internal_object;
+ tmp_inode *s_pipe = s_inode->internal_object;
+ f_pipe->read_inode = s_inode;
+ s_pipe->read_inode = f_inode;
+ f_pipe->is_closed = 0;
+ s_pipe->is_closed = 0;
+}
diff --git a/fs/tmpfs.h b/fs/tmpfs.h
new file mode 100644
index 0000000..4052bd5
--- /dev/null
+++ b/fs/tmpfs.h
@@ -0,0 +1,16 @@
+#ifndef TMP_H
+#define TMP_H
+#include <fs/fifo.h>
+#include <fs/vfs.h>
+
+#define TMP_BUFFER_SIZE (1024 * 10)
+
+typedef struct {
+ FIFO_FILE *fifo;
+ uint8_t is_closed;
+ vfs_inode_t *read_inode;
+} tmp_inode;
+
+void pipe(int fd[2]);
+void dual_pipe(int fd[2]);
+#endif
diff --git a/fs/vfs.c b/fs/vfs.c
new file mode 100644
index 0000000..9842e11
--- /dev/null
+++ b/fs/vfs.c
@@ -0,0 +1,272 @@
+#include <assert.h>
+#include <errno.h>
+#include <fs/vfs.h>
+#include <mmu.h>
+#include <poll.h>
+
+vfs_inode_t *root_dir;
+vfs_mounts_t mounts[10];
+int num_mounts = 0;
+
+vfs_fd_t *get_vfs_fd(int fd) {
+ if (fd >= 100) {
+ klog("get_vfs_fd(): Tried to get out of range fd", LOG_WARN);
+ dump_backtrace(12);
+ return NULL;
+ }
+ if (fd < 0) {
+ klog("get_vfs_fd(): Tried to get out of range fd", LOG_WARN);
+ dump_backtrace(12);
+ return NULL;
+ }
+ return get_current_task()->file_descriptors[fd];
+}
+
+vfs_inode_t *vfs_create_inode(
+ int inode_num, int type, uint8_t has_data, uint8_t can_write,
+ uint8_t is_open, void *internal_object, uint64_t file_size,
+ vfs_inode_t *(*open)(const char *path),
+ int (*create_file)(const char *path, int mode),
+ int (*read)(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd),
+ int (*write)(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd),
+ void (*close)(vfs_fd_t *fd),
+ vfs_vm_object_t *(*get_vm_object)(uint64_t length, uint64_t offset,
+ vfs_fd_t *fd)) {
+ vfs_inode_t *r = kmalloc(sizeof(inode_t));
+ r->inode_num = inode_num;
+ r->type = type;
+ r->has_data = has_data;
+ r->can_write = can_write;
+ r->is_open = is_open;
+ r->internal_object = internal_object;
+ r->file_size = file_size;
+ r->open = open;
+ r->create_file = create_file;
+ r->read = read;
+ r->write = write;
+ r->close = close;
+ r->get_vm_object = get_vm_object;
+ return r;
+}
+
+int vfs_create_fd(int flags, int mode, vfs_inode_t *inode, vfs_fd_t **fd) {
+ process_t *p = (process_t *)get_current_task();
+ int i;
+ for (i = 0; i < 100; i++)
+ if (!p->file_descriptors[i])
+ break;
+ if (p->file_descriptors[i])
+ return -1;
+ vfs_fd_t *r = kmalloc(sizeof(vfs_fd_t));
+ r->flags = flags;
+ r->mode = mode;
+ r->inode = inode;
+ r->reference_count = 1;
+ p->file_descriptors[i] = r;
+ if (fd)
+ *fd = r;
+ return i;
+}
+
+int vfs_create_file(const char *file) {
+ vfs_mounts_t *file_mount = 0;
+ int length = 0;
+ for (int i = 0; i < num_mounts; i++) {
+ int path_len = strlen(mounts[i].path);
+ if (path_len <= length)
+ continue;
+
+ if (isequal_n(mounts[i].path, file, path_len)) {
+ length = path_len;
+ file_mount = &mounts[i];
+ }
+ }
+ if (1 != length)
+ file += length;
+
+ if (!file_mount) {
+ kprintf("vfs_internal_open could not find mounted path for file : %s\n",
+ file);
+ return 0;
+ }
+ // ext2_create_file("/etc/oscreated", 0);
+ assert(file_mount->local_root->create_file);
+ kprintf("Creating a file\n");
+ return file_mount->local_root->create_file(file, 0);
+}
+
+vfs_inode_t *vfs_internal_open(const char *file) {
+ vfs_mounts_t *file_mount = 0;
+ int length = 0;
+ for (int i = 0; i < num_mounts; i++) {
+ int path_len = strlen(mounts[i].path);
+ if (path_len <= length)
+ continue;
+
+ if (isequal_n(mounts[i].path, file, path_len)) {
+ length = path_len;
+ file_mount = &mounts[i];
+ }
+ }
+ if (1 != length)
+ file += length;
+
+ if (!file_mount) {
+ kprintf("vfs_internal_open could not find mounted path for file : %s\n",
+ file);
+ return NULL;
+ }
+
+ vfs_inode_t *ret = file_mount->local_root->open(file);
+ return ret;
+}
+
+char *vfs_clean_path(const char *path, char *resolved_path) {
+ // char *const clean = kmalloc(strlen(path) + 1);
+ char *clean = resolved_path;
+ int prev_slash = 0;
+ char *ptr = clean;
+ for (; *path; path++) {
+ if (prev_slash && '/' == *path) {
+ continue;
+ }
+ prev_slash = ('/' == *path);
+ *ptr = *path;
+ ptr++;
+ }
+ *ptr = '\0';
+ return clean;
+}
+
+char *vfs_resolve_path(const char *file, char *resolved_path) {
+ if ('/' == *file) {
+ return vfs_clean_path(file, resolved_path);
+ }
+ const char *cwd = get_current_task()->current_working_directory;
+ size_t l = strlen(cwd);
+ assert(l > 0);
+ assert('/' == cwd[l - 1]);
+ // char *r = kmalloc(l + strlen(file) + 1);
+ char r[256];
+ strcpy(r, cwd);
+ strcat(r, file);
+ char *final = vfs_clean_path(r, resolved_path);
+ // kfree(r);
+ return final;
+}
+
+int vfs_open(const char *file, int flags, int mode) {
+ char resolved_path[256] = {0};
+ vfs_resolve_path(file, resolved_path);
+ vfs_inode_t *inode = vfs_internal_open(resolved_path);
+ if (0 == inode) {
+ if (mode & O_CREAT) {
+ if (vfs_create_file(resolved_path)) {
+ klog("VFS: File created", LOG_NOTE);
+ return vfs_open(file, flags, mode);
+ }
+ klog("VFS: Could not create file", LOG_WARN);
+ }
+ return -ENOENT;
+ }
+ if (inode->type == FS_TYPE_UNIX_SOCKET) {
+ return uds_open(resolved_path);
+ }
+
+ return vfs_create_fd(flags, mode, inode, NULL);
+}
+
+int vfs_close(int fd) {
+ vfs_fd_t *fd_ptr = get_vfs_fd(fd);
+ if (NULL == fd_ptr) {
+ return -1;
+ }
+ assert(0 < fd_ptr->reference_count);
+ // Remove process reference
+ fd_ptr->reference_count--;
+ get_current_task()->file_descriptors[fd] = 0;
+ // If no references left then free the contents
+ if (0 == fd_ptr->reference_count) {
+ if (fd_ptr->inode->close)
+ fd_ptr->inode->close(fd_ptr);
+
+ kfree(fd_ptr);
+ }
+ return 0;
+}
+
+int raw_vfs_pread(vfs_fd_t *vfs_fd, void *buf, uint64_t count,
+ uint64_t offset) {
+ if (!(vfs_fd->flags & O_READ))
+ return -EBADF;
+ return vfs_fd->inode->read(buf, offset, count, vfs_fd);
+}
+
+int vfs_pread(int fd, void *buf, uint64_t count, uint64_t offset) {
+ if (fd >= 100) {
+ kprintf("EBADF : %x\n", fd);
+ return -EBADF;
+ }
+ if (fd < 0) {
+ dump_backtrace(12);
+ kprintf("EBADF : %x\n", fd);
+ return -EBADF;
+ }
+ vfs_fd_t *vfs_fd = get_current_task()->file_descriptors[fd];
+ if (!vfs_fd)
+ return -EBADF;
+ int rc = raw_vfs_pread(vfs_fd, buf, count, offset);
+ if (-EAGAIN == rc && count > 0) {
+ if (!(vfs_fd->flags & O_NONBLOCK)) {
+ struct pollfd fds;
+ fds.fd = fd;
+ fds.events = POLLIN;
+ fds.revents = 0;
+ poll(&fds, 1, 0);
+ return vfs_pread(fd, buf, count, offset);
+ }
+ }
+ return rc;
+}
+
+int raw_vfs_pwrite(vfs_fd_t *vfs_fd, void *buf, uint64_t count,
+ uint64_t offset) {
+ assert(vfs_fd);
+ assert(vfs_fd->inode);
+ assert(vfs_fd->inode->write);
+ return vfs_fd->inode->write(buf, offset, count, vfs_fd);
+}
+
+int vfs_pwrite(int fd, void *buf, uint64_t count, uint64_t offset) {
+ vfs_fd_t *vfs_fd = get_vfs_fd(fd);
+ if (!vfs_fd)
+ return -EBADF;
+ if (!(vfs_fd->flags & O_WRITE)) {
+ return -EBADF;
+ }
+ return raw_vfs_pwrite(vfs_fd, buf, count, offset);
+}
+
+vfs_vm_object_t *vfs_get_vm_object(int fd, uint64_t length, uint64_t offset) {
+ vfs_fd_t *vfs_fd = get_vfs_fd(fd);
+ if (!vfs_fd)
+ return NULL;
+ vfs_vm_object_t *r = vfs_fd->inode->get_vm_object(length, offset, vfs_fd);
+ return r;
+}
+
+int vfs_dup2(int org_fd, int new_fd) {
+ get_current_task()->file_descriptors[new_fd] =
+ get_current_task()->file_descriptors[org_fd];
+ get_current_task()->file_descriptors[new_fd]->reference_count++;
+ return 1;
+}
+
+void vfs_mount(char *path, vfs_inode_t *local_root) {
+ int len = strlen(path);
+ mounts[num_mounts].path = kmalloc_eternal(len + 1);
+ memcpy(mounts[num_mounts].path, path, len);
+ mounts[num_mounts].path[len] = '\0';
+ mounts[num_mounts].local_root = local_root;
+ num_mounts++;
+}
diff --git a/fs/vfs.h b/fs/vfs.h
new file mode 100644
index 0000000..b3ef3e1
--- /dev/null
+++ b/fs/vfs.h
@@ -0,0 +1,94 @@
+typedef struct vfs_fd vfs_fd_t;
+typedef struct vfs_inode vfs_inode_t;
+typedef struct vfs_vm_object vfs_vm_object_t;
+typedef struct vfs_mounts vfs_mounts_t;
+#ifndef VFS_H
+#define VFS_H
+#include <limits.h>
+#include <sched/scheduler.h>
+#include <socket.h>
+#include <stddef.h>
+#include <stdint.h>
+
+// FIXME: Is there some standard value for this?
+#define O_NONBLOCK (1 << 0)
+#define O_READ (1 << 1)
+#define O_WRITE (1 << 2)
+#define O_CREAT (1 << 3)
+#define O_RDONLY O_READ
+#define O_WRONLY O_WRITE
+#define O_RDWR (O_WRITE | O_READ)
+
+#define FS_TYPE_FILE 0
+#define FS_TYPE_UNIX_SOCKET 1
+#define FS_TYPE_CHAR_DEVICE 2
+#define FS_TYPE_BLOCK_DEVICE 3
+#define FS_TYPE_DIRECTORY 4
+#define FS_TYPE_LINK 7
+
+struct vfs_vm_object {
+ void *virtual_object;
+ void **object;
+ uint64_t size;
+};
+
+struct vfs_mounts {
+ char *path;
+ vfs_inode_t *local_root;
+};
+
+struct dirent {
+ unsigned int d_ino; // File serial number.
+ char d_name[PATH_MAX]; // Filename string of entry.
+};
+
+struct vfs_fd {
+ size_t offset;
+ int flags;
+ int mode;
+ int reference_count; // Number of usages of this file descriptor,
+ // once it reaches zero then the contents can
+ // be freed.
+ vfs_inode_t *inode;
+};
+
+struct vfs_inode {
+ int inode_num;
+ int type;
+ uint8_t has_data;
+ uint8_t can_write;
+ uint8_t is_open;
+ void *internal_object;
+ uint64_t file_size;
+ vfs_inode_t *(*open)(const char *path);
+ int (*create_file)(const char *path, int mode);
+ int (*read)(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd);
+ int (*write)(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd);
+ void (*close)(vfs_fd_t *fd);
+ vfs_vm_object_t *(*get_vm_object)(uint64_t length, uint64_t offset,
+ vfs_fd_t *fd);
+};
+
+int vfs_close(int fd);
+vfs_fd_t *get_vfs_fd(int fd);
+int vfs_open(const char *file, int flags, int mode);
+void vfs_mount(char *path, vfs_inode_t *local_root);
+int vfs_pwrite(int fd, void *buf, uint64_t count, uint64_t offset);
+int raw_vfs_pwrite(vfs_fd_t *vfs_fd, void *buf, uint64_t count,
+ uint64_t offset);
+int vfs_pread(int fd, void *buf, uint64_t count, uint64_t offset);
+vfs_vm_object_t *vfs_get_vm_object(int fd, uint64_t length, uint64_t offset);
+int vfs_dup2(int org_fd, int new_fd);
+vfs_inode_t *vfs_internal_open(const char *file);
+int vfs_create_fd(int flags, int mode, vfs_inode_t *inode, vfs_fd_t **fd);
+vfs_inode_t *vfs_create_inode(
+ int inode_num, int type, uint8_t has_data, uint8_t can_write,
+ uint8_t is_open, void *internal_object, uint64_t file_size,
+ vfs_inode_t *(*open)(const char *path),
+ int (*create_file)(const char *path, int mode),
+ int (*read)(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd),
+ int (*write)(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd),
+ void (*close)(vfs_fd_t *fd),
+ vfs_vm_object_t *(*get_vm_object)(uint64_t length, uint64_t offset,
+ vfs_fd_t *fd));
+#endif
diff --git a/halts.c b/halts.c
new file mode 100644
index 0000000..821299d
--- /dev/null
+++ b/halts.c
@@ -0,0 +1,102 @@
+#include <assert.h>
+#include <halts.h>
+#include <sched/scheduler.h>
+
+int create_disconnect_inode_halt(vfs_inode_t *inode) {
+ volatile process_t *p = get_current_task();
+ int i;
+ for (i = 0; i < 100; i++)
+ if (!p->disconnect_halt_inode[i])
+ break;
+
+ if (p->disconnect_halt_inode[i])
+ return -1;
+
+ p->disconnect_halt_inode[i] = inode;
+
+ return i;
+}
+
+int create_disconnect_fdhalt(vfs_fd_t *fd) {
+ assert(fd);
+ return create_disconnect_inode_halt(fd->inode);
+}
+
+int create_read_inode_halt(vfs_inode_t *inode) {
+ volatile process_t *p = get_current_task();
+ int i;
+ for (i = 0; i < 100; i++)
+ if (!p->read_halt_inode[i])
+ break;
+
+ if (p->read_halt_inode[i])
+ return -1;
+
+ p->read_halt_inode[i] = inode;
+
+ return i;
+}
+
+int create_read_fdhalt(vfs_fd_t *fd) {
+ assert(fd);
+ return create_read_inode_halt(fd->inode);
+}
+
+int create_write_inode_halt(vfs_inode_t *inode) {
+ volatile process_t *p = get_current_task();
+ int i;
+ for (i = 0; i < 100; i++)
+ if (!p->write_halt_inode[i])
+ break;
+
+ if (p->write_halt_inode[i])
+ return -1;
+
+ p->write_halt_inode[i] = inode;
+
+ return i;
+}
+
+int create_write_fdhalt(vfs_fd_t *fd) {
+ return create_write_inode_halt(fd->inode);
+}
+
+void unset_read_fdhalt(int i) { get_current_task()->read_halt_inode[i] = NULL; }
+
+void unset_write_fdhalt(int i) {
+ get_current_task()->write_halt_inode[i] = NULL;
+}
+
+void unset_disconnect_fdhalt(int i) {
+ get_current_task()->disconnect_halt_inode[i] = NULL;
+}
+
+int isset_fdhalt(vfs_inode_t *read_halts[], vfs_inode_t *write_halts[],
+ vfs_inode_t *disconnect_halts[]) {
+ int blocked = 0;
+ for (int i = 0; i < 100; i++) {
+ if (!read_halts[i])
+ continue;
+ if (read_halts[i]->has_data) {
+ return 0;
+ }
+ blocked = 1;
+ }
+ for (int i = 0; i < 100; i++) {
+ if (!write_halts[i])
+ continue;
+ if (write_halts[i]->can_write) {
+ return 0;
+ }
+ blocked = 1;
+ }
+ for (int i = 0; i < 100; i++) {
+ if (!disconnect_halts[i])
+ continue;
+ if (!disconnect_halts[i]->is_open) {
+ return 0;
+ }
+ blocked = 1;
+ }
+ return blocked;
+}
diff --git a/halts.h b/halts.h
new file mode 100644
index 0000000..bd71673
--- /dev/null
+++ b/halts.h
@@ -0,0 +1,21 @@
+#ifndef HALTS_H
+#define HALTS_H
+#include <fs/vfs.h>
+#include <stdint.h>
+
+typedef struct {
+ uint8_t *ptr;
+ uint8_t active;
+} halt_t;
+
+int create_read_fdhalt(vfs_fd_t *fd);
+int create_read_inode_halt(vfs_inode_t *inode);
+void unset_read_fdhalt(int i);
+int create_write_fdhalt(vfs_fd_t *fd);
+int create_write_inode_halt(vfs_inode_t *inode);
+void unset_write_fdhalt(int i);
+int create_disconnect_fdhalt(vfs_fd_t *fd);
+void unset_disconnect_fdhalt(int i);
+int isset_fdhalt(vfs_inode_t *read_halts[], vfs_inode_t *write_halts[],
+ vfs_inode_t *disconnect_halts[]);
+#endif
diff --git a/hashmap b/hashmap
new file mode 160000
+Subproject 07dfe3b606e0d82b2e181b27344b5e4ce8849f3
diff --git a/includes/defs.h b/includes/defs.h
new file mode 100644
index 0000000..3a373b3
--- /dev/null
+++ b/includes/defs.h
@@ -0,0 +1,5 @@
+#ifndef DEFS_H
+#define DEFS_H
+#define BYTE unsigned char
+#define BYTEPTR BYTE*
+#endif
diff --git a/includes/mmu.h b/includes/mmu.h
new file mode 100644
index 0000000..39c951b
--- /dev/null
+++ b/includes/mmu.h
@@ -0,0 +1,61 @@
+#ifndef PAGING_H
+#define PAGING_H
+#include "kmalloc.h"
+#include <stdint.h>
+
+typedef uint8_t mmu_flags;
+
+#define MMU_FLAG_RW (1 << 0)
+#define MMU_FLAG_KERNEL (1 << 1)
+
+void *next_page(void *a);
+void *align_page(void *a);
+
+typedef struct Page {
+ uint32_t present : 1;
+ uint32_t rw : 1;
+ uint32_t user : 1;
+ uint32_t accessed : 1;
+ uint32_t dirty : 1;
+ uint32_t unused : 7;
+ uint32_t frame : 20;
+} __attribute__((packed)) Page;
+
+typedef struct PageTable {
+ Page pages[1024];
+} __attribute__((packed)) PageTable;
+
+typedef struct PageDirectory {
+ PageTable *tables[1024];
+ uint32_t physical_tables[1024];
+ uint32_t physical_address;
+} PageDirectory;
+
+int mmu_allocate_region(void *ptr, size_t n, mmu_flags flags);
+void mmu_allocate_shared_kernel_region(void *rc, size_t n);
+void *mmu_find_unallocated_virtual_range(void *addr, size_t length);
+void mmu_remove_virtual_physical_address_mapping(void *ptr, size_t length);
+void mmu_free_address_range(void *ptr, size_t length);
+void mmu_map_directories(void *dst, PageDirectory *d, void *src,
+ PageDirectory *s, size_t length);
+uint32_t mmu_get_number_of_allocated_frames(void);
+void *mmu_map_frames(void *ptr, size_t s);
+void mmu_map_physical(void *dst, PageDirectory *d, void *physical,
+ size_t length);
+void mmu_free_pages(void *a, uint32_t n);
+
+void flush_tlb(void);
+void paging_init(void);
+PageDirectory *get_active_pagedirectory(void);
+void move_stack(uint32_t new_stack_address, uint32_t size);
+void switch_page_directory(PageDirectory *directory);
+void *allocate_frame(Page *page, int rw, int is_kernel);
+PageDirectory *clone_directory(PageDirectory *original);
+void *virtual_to_physical(void *address, PageDirectory *directory);
+void *is_valid_userpointer(const void *const p, size_t s);
+void *is_valid_user_c_string(const char *ptr, size_t *size);
+void *ksbrk(size_t s);
+
+Page *get_page(void *ptr, PageDirectory *directory, int create_new_page,
+ int set_user);
+#endif
diff --git a/includes/sys/types.h b/includes/sys/types.h
new file mode 100644
index 0000000..1ccbf63
--- /dev/null
+++ b/includes/sys/types.h
@@ -0,0 +1,2 @@
+typedef int time_t;
+typedef int pid_t;
diff --git a/init/kernel.c b/init/kernel.c
new file mode 100644
index 0000000..9f507e0
--- /dev/null
+++ b/init/kernel.c
@@ -0,0 +1,101 @@
+#include <assert.h>
+#include <cpu/gdt.h>
+#include <cpu/idt.h>
+#include <cpu/spinlock.h>
+#include <cpu/syscall.h>
+#include <crypto/SHA1/sha1.h>
+#include <drivers/ata.h>
+#include <drivers/keyboard.h>
+#include <drivers/mouse.h>
+#include <drivers/pit.h>
+#include <drivers/serial.h>
+#include <drivers/vbe.h>
+#include <fs/devfs.h>
+#include <fs/ext2.h>
+#include <fs/shm.h>
+#include <fs/vfs.h>
+#include <log.h>
+#include <mmu.h>
+#include <multiboot.h>
+#include <random.h>
+#include <sched/scheduler.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#if defined(__linux__)
+#error "You are not using a cross-compiler."
+#endif
+
+#if !defined(__i386__)
+#error "This OS needs to be compiled with a ix86-elf compiler"
+#endif
+
+uint32_t inital_esp;
+uintptr_t data_end;
+
+void kernel_main(uint32_t kernel_end, unsigned long magic, unsigned long addr,
+ uint32_t inital_stack) {
+ data_end = kernel_end;
+ inital_esp = inital_stack;
+
+ asm("cli");
+ kprintf("If you see this then the serial driver works :D.\n");
+ assert(magic == MULTIBOOT_BOOTLOADER_MAGIC);
+
+ paging_init();
+ klog("Paging Initalized", LOG_SUCCESS);
+ multiboot_info_t *mb =
+ mmu_map_frames((multiboot_info_t *)addr, sizeof(multiboot_info_t));
+
+ gdt_init();
+ klog("GDT Initalized", LOG_SUCCESS);
+
+ idt_init();
+ klog("IDT Initalized", LOG_SUCCESS);
+
+ syscalls_init();
+ klog("Syscalls Initalized", LOG_SUCCESS);
+
+ pit_install();
+ set_pit_count(2000);
+ klog("PIT driver installed", LOG_SUCCESS);
+
+ ata_init();
+ klog("ATA Initalized", LOG_SUCCESS);
+
+ tasking_init();
+ klog("Tasking Initalized", LOG_SUCCESS);
+
+ install_mouse();
+ klog("PS2 Mouse driver installed", LOG_SUCCESS);
+
+ install_keyboard();
+ klog("PS2 Keyboard driver installed", LOG_SUCCESS);
+
+ vfs_mount("/", ext2_mount());
+ vfs_mount("/dev", devfs_mount());
+ add_stdout();
+ add_serial();
+ add_random_devices();
+ shm_init();
+
+ setup_random();
+
+ add_keyboard();
+ add_mouse();
+
+ display_driver_init(mb);
+ add_vbe_device();
+ int pid;
+ if (0 == (pid = fork())) {
+ char *argv[] = {"/init", NULL};
+ if (0 == exec("/init", argv)) {
+ kprintf("exec() failed\n");
+ }
+ }
+ for (;;)
+ ;
+}
diff --git a/isodir/boot/grub/grub.cfg b/isodir/boot/grub/grub.cfg
new file mode 100644
index 0000000..b2f8404
--- /dev/null
+++ b/isodir/boot/grub/grub.cfg
@@ -0,0 +1,3 @@
+menuentry "myos" {
+ multiboot /boot/myos.bin
+}
diff --git a/kmalloc.c b/kmalloc.c
new file mode 100644
index 0000000..f3c8238
--- /dev/null
+++ b/kmalloc.c
@@ -0,0 +1,233 @@
+#include <assert.h>
+#include <kmalloc.h>
+#include <ksbrk.h>
+#define NEW_ALLOC_SIZE 0x30000
+
+#define IS_FREE (1 << 0)
+#define IS_FINAL (1 << 1)
+
+typedef struct MallocHeader {
+ uint64_t magic;
+ uint32_t size;
+ uint8_t flags;
+ struct MallocHeader *n;
+} MallocHeader;
+
+size_t max(size_t a, size_t b) { return (a > b) ? a : b; }
+
+size_t min(size_t a, size_t b) { return (a < b) ? a : b; }
+
+uint64_t delta_page(uint64_t a) { return 0x1000 - (a % 0x1000); }
+
+MallocHeader *head = NULL;
+MallocHeader *final = NULL;
+uint32_t total_heap_size = 0;
+
+int init_heap(void) {
+ head = (MallocHeader *)ksbrk(NEW_ALLOC_SIZE);
+ total_heap_size += NEW_ALLOC_SIZE - sizeof(MallocHeader);
+ head->magic = 0xdde51ab9410268b1;
+ head->size = NEW_ALLOC_SIZE - sizeof(MallocHeader);
+ head->flags = IS_FREE | IS_FINAL;
+ head->n = NULL;
+ final = head;
+ return 1;
+}
+
+int add_heap_memory(size_t min_desired) {
+ min_desired += sizeof(MallocHeader) + 0x1000;
+ size_t allocation_size = max(min_desired, NEW_ALLOC_SIZE);
+ allocation_size += delta_page(allocation_size);
+ void *p;
+ if ((void *)(-1) == (p = (void *)ksbrk(allocation_size))) {
+ return 0;
+ }
+ total_heap_size += allocation_size - sizeof(MallocHeader);
+ void *e = final;
+ e = (void *)((uint32_t)e + final->size);
+ if (p == e) {
+ final->size += allocation_size - sizeof(MallocHeader);
+ return 1;
+ }
+ MallocHeader *new_entry = p;
+ new_entry->size = allocation_size - sizeof(MallocHeader);
+ new_entry->flags = IS_FREE | IS_FINAL;
+ new_entry->n = NULL;
+ new_entry->magic = 0xdde51ab9410268b1;
+ final->n = new_entry;
+ final = new_entry;
+ return 1;
+}
+
+MallocHeader *next_header(MallocHeader *a) {
+ assert(a->magic == 0xdde51ab9410268b1);
+ if (a->n) {
+ assert(a->n->magic == 0xdde51ab9410268b1);
+ return a->n;
+ }
+ return NULL;
+}
+
+MallocHeader *next_close_header(MallocHeader *a) {
+ if (!a) {
+ kprintf("next close header fail\n");
+ for (;;)
+ ;
+ }
+ if (a->flags & IS_FINAL)
+ return NULL;
+ return next_header(a);
+}
+
+MallocHeader *find_free_entry(uint32_t s) {
+ // A new header is required as well as the newly allocated chunk
+ s += sizeof(MallocHeader);
+ if (!head)
+ init_heap();
+ MallocHeader *p = head;
+ for (; p; p = next_header(p)) {
+ assert(p->magic == 0xdde51ab9410268b1);
+ if (!(p->flags & IS_FREE))
+ continue;
+ uint64_t required_size = s;
+ if (p->size < required_size)
+ continue;
+ return p;
+ }
+ return NULL;
+}
+
+void merge_headers(MallocHeader *b) {
+ if (!(b->flags & IS_FREE))
+ return;
+
+ MallocHeader *n = next_close_header(b);
+ if (!n)
+ return;
+
+ if (!(n->flags & IS_FREE))
+ return;
+
+ b->size += n->size;
+ b->flags |= n->flags & IS_FINAL;
+ b->n = n->n;
+ if (n == final)
+ final = b;
+}
+
+void *kmalloc(size_t s) {
+ size_t n = s;
+ MallocHeader *free_entry = find_free_entry(s);
+ if (!free_entry) {
+ if (!add_heap_memory(s)) {
+ klog("Ran out of memory.", LOG_ERROR);
+ assert(0);
+ return NULL;
+ }
+ return kmalloc(s);
+ }
+
+ void *rc = (void *)(free_entry + 1);
+
+ // Create a new header
+ MallocHeader *new_entry = (MallocHeader *)((uintptr_t)rc + n);
+ new_entry->flags = free_entry->flags;
+ new_entry->n = free_entry->n;
+ new_entry->size = free_entry->size - n - sizeof(MallocHeader);
+ new_entry->magic = 0xdde51ab9410268b1;
+
+ if (free_entry == final)
+ final = new_entry;
+ merge_headers(new_entry);
+
+ // Modify the free entry
+ free_entry->size = n;
+ free_entry->flags = 0;
+ free_entry->n = new_entry;
+ free_entry->magic = 0xdde51ab9410268b1;
+ return rc;
+}
+
+#define HEAP 0x00E00000
+#define PHYS 0x403000
+
+void *latest = NULL;
+uint64_t left = 0;
+
+void *kmalloc_eternal_physical_align(size_t s, void **physical) {
+ void *return_address = ksbrk(s);
+ if (physical) {
+ if (0 == get_active_pagedirectory())
+ *physical =
+ (void *)((uintptr_t)return_address - (0xC0000000 + PHYS) + HEAP);
+ else
+ *physical = (void *)virtual_to_physical(return_address, 0);
+ }
+ memset(return_address, 0, 0x1000);
+ return return_address;
+}
+
+void *kmalloc_eternal_align(size_t s) {
+ return kmalloc_eternal_physical_align(s, NULL);
+}
+
+void *kmalloc_eternal(size_t s) { return kmalloc_eternal_align(s); }
+
+size_t get_mem_size(void *ptr) {
+ if (!ptr)
+ return 0;
+ return ((MallocHeader *)((uintptr_t)ptr - sizeof(MallocHeader)))->size;
+}
+
+void *krealloc(void *ptr, size_t size) {
+ void *rc = kmalloc(size);
+ if (!rc)
+ return NULL;
+ if (!ptr)
+ return rc;
+ size_t l = get_mem_size(ptr);
+ size_t to_copy = min(l, size);
+ memcpy(rc, ptr, to_copy);
+ // kfree(ptr);
+ return rc;
+}
+
+// This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
+// if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
+#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4))
+
+void *kreallocarray(void *ptr, size_t nmemb, size_t size) {
+ if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && nmemb > 0 &&
+ SIZE_MAX / nmemb < size) {
+ return NULL;
+ }
+
+ return krealloc(ptr, nmemb * size);
+}
+
+void *kallocarray(size_t nmemb, size_t size) {
+ return kreallocarray(NULL, nmemb, size);
+}
+
+void *kcalloc(size_t nelem, size_t elsize) {
+ void *rc = kallocarray(nelem, elsize);
+ if (!rc)
+ return NULL;
+ memset(rc, 0, nelem * elsize);
+ return rc;
+}
+
+void kfree(void *p) {
+ /*
+if (!p)
+return;
+// FIXME: This assumes that p is at the start of a allocated area.
+// Could this be avoided in a simple way?
+MallocHeader *h = (MallocHeader *)((uintptr_t)p - sizeof(MallocHeader));
+assert(h->magic == 0xdde51ab9410268b1);
+if (h->flags & IS_FREE)
+return;
+
+h->flags |= IS_FREE;
+merge_headers(h);*/
+}
diff --git a/kmalloc.h b/kmalloc.h
new file mode 100644
index 0000000..69e0de3
--- /dev/null
+++ b/kmalloc.h
@@ -0,0 +1,21 @@
+#include <log.h>
+#include <mmu.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+void kmalloc_allocate_heap(void);
+
+void *kmalloc_eternal(size_t size);
+void *kmalloc_eternal_align(size_t size);
+void *kmalloc_eternal_physical(size_t size, void **physical);
+void *kmalloc_eternal_physical_align(size_t size, void **physical);
+
+void *kmalloc(size_t s);
+void *kmalloc_align(size_t s);
+void *krealloc(void *ptr, size_t size);
+void *kreallocarray(void *ptr, size_t nmemb, size_t size);
+void *kallocarray(size_t nmemb, size_t size);
+void *kcalloc(size_t nelem, size_t elsize);
+void kfree(void *p);
+int init_heap(void);
diff --git a/ksbrk.c b/ksbrk.c
new file mode 100644
index 0000000..755a4ed
--- /dev/null
+++ b/ksbrk.c
@@ -0,0 +1,40 @@
+#include <assert.h>
+#include <ksbrk.h>
+#include <mmu.h>
+#include <stddef.h>
+#include <stdint.h>
+
+/*
+extern uintptr_t data_end;
+extern PageDirectory *kernel_directory;
+
+#define HEAP 0x00E00000
+#define PHYS 0x403000
+#define PAGE_SIZE ((uintptr_t)0x1000)
+void *ksbrk(size_t s) {
+ uintptr_t rc = (uintptr_t)align_page((void *)data_end);
+ data_end += s;
+ data_end = (uintptr_t)align_page((void *)data_end);
+
+ if (!get_active_pagedirectory()) {
+ // If there is no active pagedirectory we
+ // just assume that the memory is
+ // already mapped.
+ return (void *)rc;
+ }
+ mmu_allocate_shared_kernel_region((void *)rc, (data_end - (uintptr_t)rc));
+ assert(((uintptr_t)rc % PAGE_SIZE) == 0);
+ memset((void *)rc, 0xFF, s);
+ return (void *)rc;
+}
+
+void *ksbrk_physical(size_t s, void **physical) {
+ void *r = ksbrk(s);
+ if (physical) {
+ // if (0 == get_active_pagedirectory())
+ // *physical = (void *)((uintptr_t)r - (0xC0000000 + PHYS) + HEAP);
+ // else
+ *physical = (void *)virtual_to_physical(r, 0);
+ }
+ return r;
+}*/
diff --git a/ksbrk.h b/ksbrk.h
new file mode 100644
index 0000000..34987dc
--- /dev/null
+++ b/ksbrk.h
@@ -0,0 +1,8 @@
+#ifndef KSBRK_H
+#define KSBRK_H
+#include <stddef.h>
+#include <stdint.h>
+
+void* ksbrk(size_t s);
+void *ksbrk_physical(size_t s, void **physical);
+#endif
diff --git a/kubsan.c b/kubsan.c
new file mode 100644
index 0000000..c81b3fc
--- /dev/null
+++ b/kubsan.c
@@ -0,0 +1,58 @@
+#include <kubsan.h>
+#include <log.h>
+#include <stdio.h>
+
+void ubsan_log(const char *cause, struct source_location source) {
+ kprintf("%s: %s : %d\n", cause, source.file_name, source.line);
+ dump_backtrace(5);
+ asm("cli");
+ asm volatile("1: jmp 1b");
+ asm("hlt");
+ for (;;)
+ ;
+}
+
+void __ubsan_handle_shift_out_of_bounds(struct ShiftOutOfBoundsData *data,
+ unsigned long lhs, unsigned long rhs) {
+ (void)lhs;
+ (void)rhs;
+ ubsan_log("handle_shift_out_of_bounds", data->location);
+}
+
+void __ubsan_handle_add_overflow(struct OverflowData *data, unsigned long lhs,
+ unsigned long rhs) {
+ (void)lhs;
+ (void)rhs;
+ ubsan_log("handle_add_overflow", data->location);
+}
+
+void __ubsan_handle_sub_overflow(struct OverflowData *data, unsigned long lhs,
+ unsigned long rhs) {
+ (void)lhs;
+ (void)rhs;
+ ubsan_log("handle_sub_overflow", data->location);
+}
+
+void __ubsan_handle_mul_overflow(struct OverflowData *data, unsigned long lhs,
+ unsigned long rhs) {
+ (void)lhs;
+ (void)rhs;
+ ubsan_log("handle_mul_overflow", data->location);
+}
+
+void __ubsan_handle_out_of_bounds(struct OutOfBoundsData *data, void *index) {
+ (void)index;
+ ubsan_log("handle_out_of_bounds", data->location);
+}
+
+void __ubsan_handle_pointer_overflow(struct OutOfBoundsData *data,
+ void *index) {
+ (void)index;
+ ubsan_log("handle_pointer_overflow", data->location);
+}
+
+void __ubsan_handle_vla_bound_not_positive(struct OutOfBoundsData *data,
+ void *index) {
+ (void)index;
+ ubsan_log("handle_vla_bound_not_positive", data->location);
+}
diff --git a/kubsan.h b/kubsan.h
new file mode 100644
index 0000000..dac5407
--- /dev/null
+++ b/kubsan.h
@@ -0,0 +1,79 @@
+#include <stdint.h>
+
+enum { type_kind_int = 0, type_kind_float = 1, type_unknown = 0xffff };
+
+struct type_descriptor {
+ uint16_t type_kind;
+ uint16_t type_info;
+ char type_name[1];
+};
+
+struct source_location {
+ const char *file_name;
+ union {
+ unsigned long reported;
+ struct {
+ uint32_t line;
+ uint32_t column;
+ };
+ };
+};
+
+struct OverflowData {
+ struct source_location location;
+ struct type_descriptor *type;
+};
+
+struct type_mismatch_data {
+ struct source_location location;
+ struct type_descriptor *type;
+ unsigned long alignment;
+ unsigned char type_check_kind;
+};
+
+struct type_mismatch_data_v1 {
+ struct source_location location;
+ struct type_descriptor *type;
+ unsigned char log_alignment;
+ unsigned char type_check_kind;
+};
+
+struct type_mismatch_data_common {
+ struct source_location *location;
+ struct type_descriptor *type;
+ unsigned long alignment;
+ unsigned char type_check_kind;
+};
+
+struct nonnull_arg_data {
+ struct source_location location;
+ struct source_location attr_location;
+ int arg_index;
+};
+
+struct OutOfBoundsData {
+ struct source_location location;
+ struct type_descriptor *array_type;
+ struct type_descriptor *index_type;
+};
+
+struct ShiftOutOfBoundsData {
+ struct source_location location;
+ struct type_descriptor *lhs_type;
+ struct type_descriptor *rhs_type;
+};
+
+struct unreachable_data {
+ struct source_location location;
+};
+
+struct invalid_value_data {
+ struct source_location location;
+ struct type_descriptor *type;
+};
+
+struct alignment_assumption_data {
+ struct source_location location;
+ struct source_location assumption_location;
+ struct type_descriptor *type;
+};
diff --git a/libc/exit/assert.c b/libc/exit/assert.c
new file mode 100644
index 0000000..b48773a
--- /dev/null
+++ b/libc/exit/assert.c
@@ -0,0 +1,12 @@
+#include <assert.h>
+#include <log.h>
+#include <stdio.h>
+#include <log.h>
+
+void aFailed(char *f, int l) {
+ kprintf("Assert failed\n");
+ kprintf("%s : %d\n", f, l);
+ dump_backtrace(10);
+ for (;;)
+ ;
+}
diff --git a/libc/include/assert.h b/libc/include/assert.h
new file mode 100644
index 0000000..90a0be4
--- /dev/null
+++ b/libc/include/assert.h
@@ -0,0 +1,19 @@
+#include <log.h>
+#include <stdio.h>
+
+#define assert(expr) \
+ { \
+ if (!(expr)) \
+ aFailed(__FILE__, __LINE__); \
+ }
+
+#define ASSERT_BUT_FIXME_PROPOGATE(expr) \
+ { \
+ if (!(expr)) \
+ kprintf("Performing assert that should have been a propogated error."); \
+ assert(expr); \
+ }
+
+void aFailed(char *f, int l);
+#define ASSERT_NOT_REACHED \
+ { assert(0) }
diff --git a/libc/include/errno.h b/libc/include/errno.h
new file mode 100644
index 0000000..1ad1004
--- /dev/null
+++ b/libc/include/errno.h
@@ -0,0 +1,85 @@
+#ifndef ERRNO_H
+#define ERRNO_H
+// https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/errno.h.html
+#define E2BIG 1 // Argument list too long.
+#define EACCES 2 // Permission denied.
+#define EADDRINUSE 3 // Address in use.
+#define EADDRNOTAVAIL 4 // Address not available.
+#define EAFNOSUPPORT 5 // Address family not supported.
+#define EAGAIN 6 // Resource unavailable, try again.
+#define EALREADY 7 // Connection already in progress.
+#define EBADF 8 // Bad file descriptor.
+#define EBADMSG 9 // Bad message.
+#define EBUSY 10 // Device or resource busy.
+#define ECANCELED 11 // Operation canceled.
+#define ECHILD 12 // No child processes.
+#define ECONNABORTED 13 // Connection aborted.
+#define ECONNREFUSED 14 // Connection refused.
+#define ECONNRESET 15 // Connection reset.
+#define EDEADLK 16 // Resource deadlock would occur.
+#define EDESTADDRREQ 17 // Destination address required.
+#define EDOM 18 // Mathematics argument out of domain of function.
+#define EDQUOT 19 // Reserved.
+#define EEXIST 20 // File exists.
+#define EFAULT 21 // Bad address.
+#define EFBIG 22 // File too large.
+#define EHOSTUNREACH 23 // Host is unreachable.
+#define EIDRM 24 // Identifier removed.
+#define EILSEQ 25 // Illegal byte sequence.
+#define EINPROGRESS 26 // Operation in progress.
+#define EINTR 27 // Interrupted function.
+#define EINVAL 28 // Invalid argument.
+#define EIO 29 // I/O error.
+#define EISCONN 30 // Socket is connected.
+#define EISDIR 31 // Is a directory.
+#define ELOOP 32 // Too many levels of symbolic links.
+#define EMFILE 33 // File descriptor value too large.
+#define EMLINK 34 // Too many links.
+#define EMSGSIZE 35 // Message too large.
+#define EMULTIHOP 36 // Reserved.
+#define ENAMETOOLONG 37 // Filename too long.
+#define ENETDOWN 38 // Network is down.
+#define ENETRESET 39 // Connection aborted by network.
+#define ENETUNREACH 40 // Network unreachable.
+#define ENFILE 41 // Too many files open in system.
+#define ENOBUFS 42 // No buffer space available.
+#define ENODATA 43 // No message is available on the STREAM head read queue.
+#define ENODEV 44 // No such device.
+#define ENOENT 45 // No such file or directory.
+#define ENOEXEC 46 // Executable file format error.
+#define ENOLCK 47 // No locks available.
+#define ENOLINK 48 // Reserved.
+#define ENOMEM 49 // Not enough space.
+#define ENOMSG 50 // No message of the desired type.
+#define ENOPROTOOPT 51 // Protocol not available.
+#define ENOSPC 52 // No space left on device.
+#define ENOSR 53 // No STREAM resources.
+#define ENOSTR 54 // Not a STREAM.
+#define ENOSYS 55 // Functionality not supported.
+#define ENOTCONN 56 // The socket is not connected.
+#define ENOTDIR 57 // Not a directory or a symbolic link to a directory.
+#define ENOTEMPTY 58 // Directory not empty.
+#define ENOTRECOVERABLE 59 // State not recoverable.
+#define ENOTSOCK 60 // Not a socket.
+#define ENOTSUP 61 // Not supported (may be the same value as.
+#define ENOTTY 62 // Inappropriate I/O control operation.
+#define ENXIO 63 // No such device or address.
+#define EOPNOTSUPP ENOTSUP // Operation not supported on socket.
+#define EOVERFLOW 65 // Value too large to be stored in data type.
+#define EOWNERDEAD 66 // Previous owner died.
+#define EPERM 67 // Operation not permitted.
+#define EPIPE 68 // Broken pipe.
+#define EPROTO 69 // Protocol error.
+#define EPROTONOSUPPORT 70 // Protocol not supported.
+#define EPROTOTYPE 71 // Protocol wrong type for socket.
+#define ERANGE 72 // Result too large.
+#define EROFS 73 // Read-only file system.
+#define ESPIPE 74 // Invalid seek.
+#define ESRCH 75 // No such process.
+#define ESTALE 76 // Reserved.
+#define ETIME 77 // Stream ioctl() timeout.
+#define ETIMEDOUT 78 // Connection timed out.
+#define ETXTBSY 79 // Text file busy.
+#define EWOULDBLOCK EAGAIN // Operation would block.
+#define EXDEV 81 // Cross-device link.
+#endif
diff --git a/libc/include/limits.h b/libc/include/limits.h
new file mode 100644
index 0000000..05022ec
--- /dev/null
+++ b/libc/include/limits.h
@@ -0,0 +1 @@
+#define PATH_MAX 256
diff --git a/libc/include/stdio.h b/libc/include/stdio.h
new file mode 100644
index 0000000..f2bbb32
--- /dev/null
+++ b/libc/include/stdio.h
@@ -0,0 +1,9 @@
+#ifndef STDIO_H
+#define STDIO_H
+
+void putc(const char c);
+int puts(char *str);
+void delete_characther(void);
+int kprintf(const char *format, ...);
+
+#endif
diff --git a/libc/include/stdlib.h b/libc/include/stdlib.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/libc/include/stdlib.h
diff --git a/libc/include/string.h b/libc/include/string.h
new file mode 100644
index 0000000..7cee4b2
--- /dev/null
+++ b/libc/include/string.h
@@ -0,0 +1,19 @@
+#ifndef STRING_H
+#define STRING_H
+#include <stddef.h>
+#include <stdint.h>
+
+unsigned long strlen(const char *s);
+void *memcpy(void *dest, const void *src, uint32_t n);
+void *memset(void *dst, const unsigned char c, uint32_t n);
+int memcmp(const void *s1, const void *s2, uint32_t n);
+char *strcpy(char *d, const char *s);
+int strcmp(const char *s1, const char *s2);
+int isequal(const char *s1, const char *s2);
+int isequal_n(const char *s1, const char *s2, uint32_t n);
+char *copy_and_allocate_string(const char *s);
+char *copy_and_allocate_user_string(const char *s);
+char *strncpy(char *dest, const char *src, size_t n);
+size_t strlcpy(char *dst, const char *src, size_t dsize);
+char *strcat(char *s1, const char *s2);
+#endif
diff --git a/libc/include/time.h b/libc/include/time.h
new file mode 100644
index 0000000..4e356d1
--- /dev/null
+++ b/libc/include/time.h
@@ -0,0 +1,6 @@
+#include <types.h>
+
+struct timespec {
+ time_t tv_sec; // Seconds.
+ long tv_nsec; // Nanoseconds.
+};
diff --git a/libc/include/types.h b/libc/include/types.h
new file mode 100644
index 0000000..ffcf281
--- /dev/null
+++ b/libc/include/types.h
@@ -0,0 +1,27 @@
+#ifndef TYPES_H
+#define TYPES_H
+typedef unsigned int ino_t;
+
+typedef int mode_t;
+
+typedef int nlink_t;
+typedef int uid_t;
+typedef int gid_t;
+typedef int id_t;
+
+typedef int blkcnt_t;
+typedef int off_t;
+
+typedef int dev_t;
+typedef unsigned int fsblkcnt_t;
+typedef unsigned int fsfilcnt_t;
+typedef unsigned int ino_t;
+//typedef unsigned int size_t;
+
+typedef int blksize_t;
+typedef int pid_t;
+typedef int ssize_t;
+
+//typedef int clock_t;
+typedef int time_t;
+#endif
diff --git a/libc/stdio/print.c b/libc/stdio/print.c
new file mode 100644
index 0000000..8174983
--- /dev/null
+++ b/libc/stdio/print.c
@@ -0,0 +1,97 @@
+#include "../../drivers/serial.h"
+#include "../include/assert.h"
+#include "../include/stdio.h"
+#include <stdarg.h>
+
+#define TAB_SIZE 8
+
+const char HEX_SET[0x10] = {'0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
+
+inline void putc(const char c) { write_serial(c); }
+
+int kprint_hex(uint64_t num) {
+ int c = 2;
+
+ if (num == 0) {
+ putc('0');
+ c++;
+ return c;
+ }
+
+ char str[16] = {0};
+ int i = 0;
+ for (; num != 0 && i < 16; i++, num /= 16)
+ str[i] = HEX_SET[(num % 16)];
+
+ c += i;
+ for (i--; i >= 0; i--)
+ putc(str[i]);
+
+ return c;
+}
+
+int kprint_int(int num) {
+ int c = 0;
+ if (0 == num) {
+ putc('0');
+ c++;
+ return c;
+ }
+ char str[10];
+ int i = 0;
+ for (; num != 0 && i < 10; i++, num /= 10)
+ str[i] = (num % 10) + '0';
+
+ c += i;
+ for (i--; i >= 0; i--)
+ putc(str[i]);
+ return c;
+}
+
+int kprintf(const char *format, ...) {
+ int c = 0;
+ va_list list;
+ va_start(list, format);
+
+ const char *s = format;
+ for (; *s; s++) {
+ if ('%' != *s) {
+ putc(*s);
+ c++;
+ continue;
+ }
+
+ char flag = *(s + 1);
+ if ('\0' == flag)
+ break;
+
+ switch (flag) {
+ case 'c':
+ putc((char)va_arg(list, int));
+ c++;
+ break;
+ case 'd':
+ c += kprint_int(va_arg(list, int));
+ break;
+ case 's':
+ for (char *string = va_arg(list, char *); *string; putc(*string++), c++)
+ ;
+ break;
+ case 'x':
+ c += kprint_hex(va_arg(list, const uint32_t));
+ break;
+ case '%':
+ putc('%');
+ c++;
+ break;
+ default:
+ ASSERT_NOT_REACHED;
+ break;
+ }
+ s++;
+ }
+ return c;
+}
+
+int puts(char *str) { return kprintf("%s\n", str); }
diff --git a/libc/string/copy.c b/libc/string/copy.c
new file mode 100644
index 0000000..277c808
--- /dev/null
+++ b/libc/string/copy.c
@@ -0,0 +1,26 @@
+#include <assert.h>
+#include <kmalloc.h>
+#include <stddef.h>
+#include <string.h>
+
+char *copy_and_allocate_string(const char *s) {
+ size_t l = strlen(s);
+ char *r = kmalloc(l + 1);
+ if (!r)
+ return NULL;
+ return strncpy(r, s, l);
+}
+
+char *copy_and_allocate_user_string(const char *s) {
+ size_t len;
+ if (!is_valid_user_c_string(s, &len))
+ return NULL;
+ size_t real_len = strlen(s);
+ assert(real_len == len);
+ len = real_len;
+ char *r = kmalloc(len + 1);
+ if (!r)
+ return NULL;
+ strlcpy(r, s, len);
+ return r;
+}
diff --git a/libc/string/isequal.c b/libc/string/isequal.c
new file mode 100644
index 0000000..cdbd3cc
--- /dev/null
+++ b/libc/string/isequal.c
@@ -0,0 +1,15 @@
+#include "../include/string.h"
+
+int isequal(const char *s1, const char *s2) {
+ for(;*s1;s1++,s2++)
+ if(*s1 != *s2)
+ return 0;
+ return 1;
+}
+
+int isequal_n(const char *s1, const char *s2, uint32_t n) {
+ for(;*s1 && n;s1++,s2++,n--)
+ if(*s1 != *s2)
+ return 0;
+ return 1;
+}
diff --git a/libc/string/memcmp.c b/libc/string/memcmp.c
new file mode 100644
index 0000000..72c680a
--- /dev/null
+++ b/libc/string/memcmp.c
@@ -0,0 +1,12 @@
+#include "../include/string.h"
+
+int memcmp(const void *s1, const void *s2, uint32_t n)
+{
+ int return_value = 0;
+
+ for(uint32_t i = 0;i < n;i++)
+ if(((unsigned char *)(s1))[i] != ((unsigned char *)(s2))[i])
+ return_value++;
+
+ return return_value;
+}
diff --git a/libc/string/memcpy.c b/libc/string/memcpy.c
new file mode 100644
index 0000000..70a60c1
--- /dev/null
+++ b/libc/string/memcpy.c
@@ -0,0 +1,11 @@
+#include "../include/string.h"
+
+void *__attribute__((optimize("O0")))
+memcpy(void *dest, const void *src, uint32_t n) {
+ unsigned char *d = dest;
+ const unsigned char *s = src;
+ // for(;n--;) *d++ = *s++;
+ for (; n; n--)
+ *d++ = *s++;
+ return dest;
+}
diff --git a/libc/string/memset.c b/libc/string/memset.c
new file mode 100644
index 0000000..a446eb4
--- /dev/null
+++ b/libc/string/memset.c
@@ -0,0 +1,9 @@
+#include <string.h>
+
+void *memset(void *dst, const unsigned char c, uint32_t n) {
+ uintptr_t d = (uintptr_t)dst;
+ for (uint32_t i = 0; i < n; i++, d++)
+ *(unsigned char *)d = c;
+
+ return (void *)d;
+}
diff --git a/libc/string/strcat.c b/libc/string/strcat.c
new file mode 100644
index 0000000..78a9ec6
--- /dev/null
+++ b/libc/string/strcat.c
@@ -0,0 +1,6 @@
+#include <string.h>
+
+char *strcat(char *s1, const char *s2) {
+ strcpy(s1 + strlen(s1), s2);
+ return s1;
+}
diff --git a/libc/string/strcmp.c b/libc/string/strcmp.c
new file mode 100644
index 0000000..d7039e2
--- /dev/null
+++ b/libc/string/strcmp.c
@@ -0,0 +1,8 @@
+#include "../include/string.h"
+
+int strcmp(const char *s1, const char *s2)
+{
+ for(;*s1 == *s2 && *s1; s1++, s2++)
+ ;
+ return *s1 - *s2;
+}
diff --git a/libc/string/strcpy.c b/libc/string/strcpy.c
new file mode 100644
index 0000000..fa1e336
--- /dev/null
+++ b/libc/string/strcpy.c
@@ -0,0 +1,8 @@
+#include <string.h>
+
+char *strcpy(char *d, const char *s) {
+ char *s1 = d;
+ for (; (*d++ = *s++);)
+ ;
+ return s1;
+}
diff --git a/libc/string/strlcpy.c b/libc/string/strlcpy.c
new file mode 100644
index 0000000..43d0e58
--- /dev/null
+++ b/libc/string/strlcpy.c
@@ -0,0 +1,21 @@
+#include <stddef.h>
+#include <string.h>
+
+// Copy string src to buffer dst of size dsize. At most dsize-1
+// chars will be copied. Always NUL terminates (unless dsize == 0).
+// Returns strlen(src); if retval >= dsize, truncation occurred.
+size_t strlcpy(char *dst, const char *src, size_t dsize) {
+ size_t n = dsize;
+ const char *osrc = src;
+ for (; n; n--) {
+ if ((*dst++ = *src++) == '\0')
+ break;
+ }
+ if (n == 0) {
+ if (dsize != 0)
+ *dst = '\0'; /* NUL-terminate dst */
+ while (*src++)
+ ;
+ }
+ return src - osrc - 1;
+}
diff --git a/libc/string/strlen.c b/libc/string/strlen.c
new file mode 100644
index 0000000..4346383
--- /dev/null
+++ b/libc/string/strlen.c
@@ -0,0 +1,8 @@
+#include "../include/string.h"
+
+unsigned long strlen(const char *s)
+{
+ const char * tmp = s;
+ for(;*tmp++;);
+ return (tmp - s)-1;
+}
diff --git a/libc/string/strncpy.c b/libc/string/strncpy.c
new file mode 100644
index 0000000..a886895
--- /dev/null
+++ b/libc/string/strncpy.c
@@ -0,0 +1,11 @@
+#include <stddef.h>
+#include <string.h>
+
+// FIXME: Something is weird with this function
+char *strncpy(char *dest, const char *src, size_t n) {
+ char *r = dest;
+ for (; n && (*dest = *src); n--, src++, dest++)
+ ;
+ *dest = '\0';
+ return r;
+}
diff --git a/linker.ld b/linker.ld
new file mode 100644
index 0000000..59b150d
--- /dev/null
+++ b/linker.ld
@@ -0,0 +1,41 @@
+ENTRY (_start)
+
+SECTIONS
+{
+ . = 0x00100000;
+ /* The kernel will live at 3GB + 1MB in the virtual address space, */
+ /* which will be mapped to 1MB in the physical address space. */
+ /* Note that we page-align the sections. */
+
+ _kernel_start = .;
+ .multiboot.data : {
+ *(.multiboot.data)
+ }
+
+ .multiboot.text : {
+ *(.multiboot.text)
+ }
+
+ . += 0xC0000000;
+ /* Add a symbol that indicates the start address of the kernel. */
+ .text ALIGN (4K) : AT (ADDR (.text) - 0xC0000000)
+ {
+ *(.text)
+ }
+ .rodata ALIGN (4K) : AT (ADDR (.rodata) - 0xC0000000)
+ {
+ *(.rodata)
+ }
+ .data ALIGN (4K) : AT (ADDR (.data) - 0xC0000000)
+ {
+ *(.data)
+ }
+ .bss ALIGN (4K) : AT (ADDR (.bss) - 0xC0000000)
+ {
+ *(COMMON)
+ *(.bss)
+ *(.bootstrap_stack)
+ }
+ /* Add a symbol that indicates the end address of the kernel. */
+ _kernel_end = .;
+}
diff --git a/log.c b/log.c
new file mode 100644
index 0000000..56d38e8
--- /dev/null
+++ b/log.c
@@ -0,0 +1,40 @@
+#include "log.h"
+#include <sched/scheduler.h>
+
+struct stackframe {
+ struct stackframe *ebp;
+ uint32_t eip;
+};
+
+void dump_backtrace(uint32_t max_frames) {
+ struct stackframe *stk;
+ asm("mov %%ebp,%0" : "=r"(stk)::);
+ kprintf("Stack trace:\n");
+ for (uint32_t frame = 0; stk && frame < max_frames; ++frame) {
+ kprintf(" 0x%x\n", stk->eip);
+ stk = stk->ebp;
+ }
+ if (get_current_task()) {
+ kprintf(" PID: %x\n", get_current_task()->pid);
+ }
+}
+
+void klog(char *str, int code) {
+ switch (code) {
+ case LOG_NOTE:
+ kprintf("[NOTE] ");
+ break;
+ case LOG_WARN:
+ kprintf("[WARN] ");
+ break;
+ case LOG_ERROR:
+ kprintf("[ERROR] ");
+ break;
+ default:
+ case LOG_SUCCESS:
+ kprintf("[SUCCESS] ");
+ break;
+ }
+
+ puts(str);
+}
diff --git a/log.h b/log.h
new file mode 100644
index 0000000..fe499bc
--- /dev/null
+++ b/log.h
@@ -0,0 +1,10 @@
+#include <stdio.h>
+#include <stdint.h>
+
+#define LOG_NOTE 3
+#define LOG_WARN 2
+#define LOG_ERROR 1
+#define LOG_SUCCESS 0
+
+void klog(char *str, int code);
+void dump_backtrace(uint32_t max_frames);
diff --git a/mount/cat b/mount/cat
new file mode 120000
index 0000000..a24e907
--- /dev/null
+++ b/mount/cat
@@ -0,0 +1 @@
+./minibox \ No newline at end of file
diff --git a/mount/init b/mount/init
new file mode 120000
index 0000000..a24e907
--- /dev/null
+++ b/mount/init
@@ -0,0 +1 @@
+./minibox \ No newline at end of file
diff --git a/mount/pid1 b/mount/pid1
new file mode 100755
index 0000000..773d54c
--- /dev/null
+++ b/mount/pid1
Binary files differ
diff --git a/mount/program b/mount/program
new file mode 100755
index 0000000..c93d7ba
--- /dev/null
+++ b/mount/program
Binary files differ
diff --git a/mount/sh b/mount/sh
new file mode 100755
index 0000000..c05684c
--- /dev/null
+++ b/mount/sh
Binary files differ
diff --git a/multiboot.h b/multiboot.h
new file mode 100644
index 0000000..ecbb6a0
--- /dev/null
+++ b/multiboot.h
@@ -0,0 +1,243 @@
+#include <stdint.h>
+#ifndef MULTIBOOT_HEADER
+#define MULTIBOOT_HEADER 1
+
+/* How many bytes from the start of the file we search for the header. */
+#define MULTIBOOT_SEARCH 8192
+#define MULTIBOOT_HEADER_ALIGN 4
+
+/* The magic field should contain this. */
+#define MULTIBOOT_HEADER_MAGIC 0x1BADB002
+
+/* This should be in %eax. */
+#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002
+
+/* Alignment of multiboot modules. */
+#define MULTIBOOT_MOD_ALIGN 0x00001000
+
+/* Alignment of the multiboot info structure. */
+#define MULTIBOOT_INFO_ALIGN 0x00000004
+
+/* Flags set in the ’flags’ member of the multiboot header. */
+
+/* Align all boot modules on i386 page (4KB) boundaries. */
+#define MULTIBOOT_PAGE_ALIGN 0x00000001
+
+/* Must pass memory information to OS. */
+#define MULTIBOOT_MEMORY_INFO 0x00000002
+
+/* Must pass video information to OS. */
+#define MULTIBOOT_VIDEO_MODE 0x00000004
+
+/* This flag indicates the use of the address fields in the header. */
+#define MULTIBOOT_AOUT_KLUDGE 0x00010000
+
+/* Flags to be set in the ’flags’ member of the multiboot info structure. */
+
+/* is there basic lower/upper memory information? */
+#define MULTIBOOT_INFO_MEMORY 0x00000001
+/* is there a boot device set? */
+#define MULTIBOOT_INFO_BOOTDEV 0x00000002
+/* is the command-line defined? */
+#define MULTIBOOT_INFO_CMDLINE 0x00000004
+/* are there modules to do something with? */
+#define MULTIBOOT_INFO_MODS 0x00000008
+
+/* These next two are mutually exclusive */
+
+/* is there a symbol table loaded? */
+#define MULTIBOOT_INFO_AOUT_SYMS 0x00000010
+/* is there an ELF section header table? */
+#define MULTIBOOT_INFO_ELF_SHDR 0X00000020
+
+/* is there a full memory map? */
+#define MULTIBOOT_INFO_MEM_MAP 0x00000040
+
+/* Is there drive info? */
+#define MULTIBOOT_INFO_DRIVE_INFO 0x00000080
+
+/* Is there a config table? */
+#define MULTIBOOT_INFO_CONFIG_TABLE 0x00000100
+
+/* Is there a boot loader name? */
+#define MULTIBOOT_INFO_BOOT_LOADER_NAME 0x00000200
+
+/* Is there a APM table? */
+#define MULTIBOOT_INFO_APM_TABLE 0x00000400
+
+/* Is there video information? */
+#define MULTIBOOT_INFO_VBE_INFO 0x00000800
+#define MULTIBOOT_INFO_FRAMEBUFFER_INFO 0x00001000
+
+#ifndef ASM_FILE
+
+typedef uint8_t multiboot_uint8_t;
+typedef uint16_t multiboot_uint16_t;
+typedef uint32_t multiboot_uint32_t;
+typedef uint64_t multiboot_uint64_t;
+
+struct multiboot_header {
+ /* Must be MULTIBOOT_MAGIC - see above. */
+ multiboot_uint32_t magic;
+
+ /* Feature flags. */
+ multiboot_uint32_t flags;
+
+ /* The above fields plus this one must equal 0 mod 2^32. */
+ multiboot_uint32_t checksum;
+
+ /* These are only valid if MULTIBOOT_AOUT_KLUDGE is set. */
+ multiboot_uint32_t header_addr;
+ multiboot_uint32_t load_addr;
+ multiboot_uint32_t load_end_addr;
+ multiboot_uint32_t bss_end_addr;
+ multiboot_uint32_t entry_addr;
+
+ /* These are only valid if MULTIBOOT_VIDEO_MODE is set. */
+ multiboot_uint32_t mode_type;
+ multiboot_uint32_t width;
+ multiboot_uint32_t height;
+ multiboot_uint32_t depth;
+};
+
+/* The symbol table for a.out. */
+struct multiboot_aout_symbol_table {
+ multiboot_uint32_t tabsize;
+ multiboot_uint32_t strsize;
+ multiboot_uint32_t addr;
+ multiboot_uint32_t reserved;
+};
+typedef struct multiboot_aout_symbol_table multiboot_aout_symbol_table_t;
+
+/* The section header table for ELF. */
+struct multiboot_elf_section_header_table {
+ multiboot_uint32_t num;
+ multiboot_uint32_t size;
+ multiboot_uint32_t addr;
+ multiboot_uint32_t shndx;
+};
+typedef struct multiboot_elf_section_header_table
+ multiboot_elf_section_header_table_t;
+
+struct multiboot_info {
+ /* Multiboot info version number */
+ multiboot_uint32_t flags;
+
+ /* Available memory from BIOS */
+ multiboot_uint32_t mem_lower;
+ multiboot_uint32_t mem_upper;
+
+ /* "root" partition */
+ multiboot_uint32_t boot_device;
+
+ /* Kernel command line */
+ multiboot_uint32_t cmdline;
+
+ /* Boot-Module list */
+ multiboot_uint32_t mods_count;
+ multiboot_uint32_t mods_addr;
+
+ union {
+ multiboot_aout_symbol_table_t aout_sym;
+ multiboot_elf_section_header_table_t elf_sec;
+ } u;
+
+ /* Memory Mapping buffer */
+ multiboot_uint32_t mmap_length;
+ multiboot_uint32_t mmap_addr;
+
+ /* Drive Info buffer */
+ multiboot_uint32_t drives_length;
+ multiboot_uint32_t drives_addr;
+
+ /* ROM configuration table */
+ multiboot_uint32_t config_table;
+
+ /* Boot Loader Name */
+ multiboot_uint32_t boot_loader_name;
+
+ /* APM table */
+ multiboot_uint32_t apm_table;
+
+ /* Video */
+ multiboot_uint32_t vbe_control_info;
+ multiboot_uint32_t vbe_mode_info;
+ multiboot_uint16_t vbe_mode;
+ multiboot_uint16_t vbe_interface_seg;
+ multiboot_uint16_t vbe_interface_off;
+ multiboot_uint16_t vbe_interface_len;
+
+ multiboot_uint64_t framebuffer_addr;
+ multiboot_uint32_t framebuffer_pitch;
+ multiboot_uint32_t framebuffer_width;
+ multiboot_uint32_t framebuffer_height;
+ multiboot_uint8_t framebuffer_bpp;
+#define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED 0
+#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB 1
+#define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT 2
+ multiboot_uint8_t framebuffer_type;
+ union {
+ struct {
+ multiboot_uint32_t framebuffer_palette_addr;
+ multiboot_uint16_t framebuffer_palette_num_colors;
+ };
+ struct {
+ multiboot_uint8_t framebuffer_red_field_position;
+ multiboot_uint8_t framebuffer_red_mask_size;
+ multiboot_uint8_t framebuffer_green_field_position;
+ multiboot_uint8_t framebuffer_green_mask_size;
+ multiboot_uint8_t framebuffer_blue_field_position;
+ multiboot_uint8_t framebuffer_blue_mask_size;
+ };
+ };
+};
+typedef struct multiboot_info multiboot_info_t;
+
+struct multiboot_color {
+ multiboot_uint8_t red;
+ multiboot_uint8_t green;
+ multiboot_uint8_t blue;
+};
+
+struct multiboot_mmap_entry {
+ multiboot_uint32_t size;
+ multiboot_uint64_t addr;
+ multiboot_uint64_t len;
+#define MULTIBOOT_MEMORY_AVAILABLE 1
+#define MULTIBOOT_MEMORY_RESERVED 2
+#define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE 3
+#define MULTIBOOT_MEMORY_NVS 4
+#define MULTIBOOT_MEMORY_BADRAM 5
+ multiboot_uint32_t type;
+} __attribute__((packed));
+typedef struct multiboot_mmap_entry multiboot_memory_map_t;
+
+struct multiboot_mod_list {
+ /* the memory used goes from bytes ’mod_start’ to ’mod_end-1’ inclusive */
+ multiboot_uint32_t mod_start;
+ multiboot_uint32_t mod_end;
+
+ /* Module command line */
+ multiboot_uint32_t cmdline;
+
+ /* padding to take it to 16 bytes (must be zero) */
+ multiboot_uint32_t pad;
+};
+typedef struct multiboot_mod_list multiboot_module_t;
+
+/* APM BIOS info. */
+struct multiboot_apm_info {
+ multiboot_uint16_t version;
+ multiboot_uint16_t cseg;
+ multiboot_uint32_t offset;
+ multiboot_uint16_t cseg_16;
+ multiboot_uint16_t dseg;
+ multiboot_uint16_t flags;
+ multiboot_uint16_t cseg_len;
+ multiboot_uint16_t cseg_16_len;
+ multiboot_uint16_t dseg_len;
+};
+
+#endif /* ! ASM_FILE */
+
+#endif /* ! MULTIBOOT_HEADER */
diff --git a/new.sh b/new.sh
new file mode 100755
index 0000000..60dcc95
--- /dev/null
+++ b/new.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+cp new_ext2.img ext2.img
+./sync.sh
diff --git a/poll.c b/poll.c
new file mode 100644
index 0000000..5e02723
--- /dev/null
+++ b/poll.c
@@ -0,0 +1,54 @@
+#include <fs/vfs.h>
+#include <halts.h>
+#include <poll.h>
+#include <sched/scheduler.h>
+
+int poll(struct pollfd *fds, size_t nfds, int timeout) {
+ (void)timeout;
+ int read_locks[nfds];
+ int write_locks[nfds];
+ int disconnect_locks[nfds];
+ for (size_t i = 0; i < nfds; i++) {
+ if (fds[i].fd < 0)
+ continue;
+ vfs_fd_t *f = get_vfs_fd(fds[i].fd);
+ if (fds[i].events & POLLIN)
+ read_locks[i] = create_read_fdhalt(f);
+ if (fds[i].events & POLLOUT)
+ write_locks[i] = create_write_fdhalt(f);
+ if (fds[i].events & POLLHUP)
+ disconnect_locks[i] = create_disconnect_fdhalt(f);
+ }
+
+ switch_task();
+
+ for (size_t i = 0; i < nfds; i++) {
+ if (fds[i].fd < 0)
+ continue;
+ if (fds[i].events & POLLIN)
+ unset_read_fdhalt(read_locks[i]);
+ if (fds[i].events & POLLOUT)
+ unset_write_fdhalt(write_locks[i]);
+ if (fds[i].events & POLLHUP)
+ unset_disconnect_fdhalt(disconnect_locks[i]);
+ }
+ for (size_t i = 0; i < nfds; i++) {
+ if (0 > fds[i].fd) {
+ fds[i].revents = 0;
+ continue;
+ }
+ vfs_fd_t *f = get_vfs_fd(fds[i].fd);
+ if (!f) {
+ if (fds[i].events & POLLHUP)
+ fds[i].revents |= POLLHUP;
+ } else {
+ if (f->inode->has_data && fds[i].events & POLLIN)
+ fds[i].revents |= POLLIN;
+ if (f->inode->can_write && fds[i].events & POLLOUT)
+ fds[i].revents |= POLLOUT;
+ if (!(f->inode->is_open) && fds[i].events & POLLHUP)
+ fds[i].revents |= POLLHUP;
+ }
+ }
+ return 0;
+}
diff --git a/poll.h b/poll.h
new file mode 100644
index 0000000..19698dd
--- /dev/null
+++ b/poll.h
@@ -0,0 +1,15 @@
+#include <stdint.h>
+#include <stddef.h>
+
+#define POLLIN (1 << 0)
+#define POLLPRI (1 << 1)
+#define POLLOUT (1 << 2)
+#define POLLHUP (1 << 3)
+
+struct pollfd {
+ int fd;
+ short events;
+ short revents;
+};
+
+int poll(struct pollfd *fds, size_t nfds, int timeout);
diff --git a/process.s b/process.s
new file mode 100644
index 0000000..24e1869
--- /dev/null
+++ b/process.s
@@ -0,0 +1,33 @@
+.intel_syntax noprefix
+.global copy_page_physical
+.global loop_m
+copy_page_physical:
+ push ebx
+ pushf
+
+ cli
+
+ mov ebx, [esp+12]
+ mov ecx, [esp+16]
+
+ mov edx, cr0
+ and edx, 0x7fffffff
+ mov cr0, edx
+
+ mov edx, 1024
+
+.loop:
+ mov eax, [ebx]
+ mov [ecx], eax
+ add ebx, 4
+ add ecx, 4
+ dec edx
+ jnz .loop
+
+ mov edx, cr0
+ or edx, 0x80000000
+ mov cr0, edx
+
+ popf
+ pop ebx
+ ret
diff --git a/random.c b/random.c
new file mode 100644
index 0000000..0e1b760
--- /dev/null
+++ b/random.c
@@ -0,0 +1,142 @@
+// FIXME: This is mostlikely incredibly inefficent and insecure.
+#include <crypto/ChaCha20/chacha20.h>
+#include <crypto/SHA1/sha1.h>
+#include <fs/devfs.h>
+#include <fs/vfs.h>
+#include <random.h>
+#include <stddef.h>
+#include <string.h>
+
+#define HASH_CTX SHA1_CTX
+#define HASH_LEN SHA1_LEN
+
+uint32_t internal_chacha_block[16] = {
+ // Constant ascii values of "expand 32-byte k"
+ 0x61707865,
+ 0x3320646e,
+ 0x79622d32,
+ 0x6b206574,
+ // The unique key
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ // Block counter
+ 0x00000000,
+ // Nonce
+ 0x00000000,
+ 0x00000000,
+};
+
+void mix_chacha(void) {
+ uint8_t rand_data[BLOCK_SIZE];
+ get_random((BYTEPTR)rand_data, BLOCK_SIZE);
+ memcpy(internal_chacha_block + KEY, rand_data, KEY_SIZE);
+ memcpy(internal_chacha_block + NONCE, rand_data + KEY_SIZE, NONCE_SIZE);
+ internal_chacha_block[COUNT] = 0;
+}
+
+void get_random(BYTEPTR buffer, uint64_t len) {
+ uint8_t rand_data[BLOCK_SIZE];
+ for (; len > 0;) {
+ if (COUNT_MAX - 1 == internal_chacha_block[COUNT]) {
+ // The current block has used up all the 2^32 counts. If the
+ // key and/or the nonce are not changed and the count
+ // overflows back to zero then the random values would
+ // repeate. This is of course not desiered behaviour. The
+ // solution is to create a new nonce and key using the
+ // already established chacha block.
+ internal_chacha_block[COUNT]++;
+ mix_chacha();
+ }
+ uint32_t read_len = (BLOCK_SIZE < len) ? (BLOCK_SIZE) : len;
+ chacha_block((uint32_t *)rand_data, internal_chacha_block);
+ internal_chacha_block[COUNT]++;
+ memcpy(buffer, rand_data, read_len);
+ buffer += read_len;
+ len -= read_len;
+ }
+}
+
+HASH_CTX hash_pool;
+uint32_t hash_pool_size = 0;
+
+void add_hash_pool(void) {
+ uint8_t new_chacha_key[KEY_SIZE];
+ get_random(new_chacha_key, KEY_SIZE);
+
+ uint8_t hash_buffer[HASH_LEN];
+ SHA1_Final(&hash_pool, hash_buffer);
+ for (size_t i = 0; i < HASH_LEN; i++)
+ new_chacha_key[i % KEY_SIZE] ^= hash_buffer[i];
+
+ SHA1_Init(&hash_pool);
+ SHA1_Update(&hash_pool, hash_buffer, HASH_LEN);
+
+ uint8_t block[BLOCK_SIZE];
+ get_random(block, BLOCK_SIZE);
+ SHA1_Update(&hash_pool, block, BLOCK_SIZE);
+
+ memcpy(internal_chacha_block + KEY, new_chacha_key, KEY_SIZE);
+
+ mix_chacha();
+}
+
+void add_entropy(uint8_t *buffer, size_t size) {
+ SHA1_Update(&hash_pool, buffer, size);
+ hash_pool_size += size;
+ if (hash_pool_size >= HASH_LEN * 2)
+ add_hash_pool();
+}
+
+void setup_random(void) {
+ SHA1_Init(&hash_pool);
+
+ BYTE seed[1024];
+ int rand_fd = vfs_open("/etc/seed", O_RDWR, 0);
+ if (0 > rand_fd) {
+ klog("/etc/seed not found", LOG_WARN);
+ return;
+ }
+
+ size_t offset = 0;
+ for (int rc; (rc = vfs_pread(rand_fd, seed, 1024, offset)); offset += rc) {
+ if (0 > rc) {
+ klog("/etc/seed read error", LOG_WARN);
+ break;
+ }
+ add_entropy(seed, rc);
+ }
+ add_hash_pool();
+
+ // Update the /etc/seed file to ensure we get a new state upon next
+ // boot.
+ get_random(seed, 1024);
+ vfs_pwrite(rand_fd, seed, 1024, 0);
+ vfs_close(rand_fd);
+}
+
+int random_write(BYTEPTR buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd) {
+ (void)offset;
+ (void)fd;
+ add_entropy(buffer, len);
+ return len; // add_entropy() never fails to recieve (len) amount of data.
+}
+
+int random_read(BYTEPTR buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd) {
+ (void)offset;
+ (void)fd;
+ get_random(buffer, len);
+ return len; // get_random() never fails to give "len" amount of data.
+}
+
+void add_random_devices(void) {
+ devfs_add_file("/random", random_read, random_write, NULL, 1, 1,
+ FS_TYPE_CHAR_DEVICE);
+ devfs_add_file("/urandom", random_read, random_write, NULL, 1, 1,
+ FS_TYPE_CHAR_DEVICE);
+}
diff --git a/random.h b/random.h
new file mode 100644
index 0000000..437927f
--- /dev/null
+++ b/random.h
@@ -0,0 +1,7 @@
+#include <stdint.h>
+#include <fs/vfs.h>
+#include <defs.h>
+
+void setup_random(void);
+void add_random_devices(void);
+void get_random(uint8_t* buffer, uint64_t len);
diff --git a/read_eip.s b/read_eip.s
new file mode 100644
index 0000000..6041db0
--- /dev/null
+++ b/read_eip.s
@@ -0,0 +1,5 @@
+.intel_syntax noprefix
+.global read_eip
+read_eip:
+ pop eax
+ jmp eax
diff --git a/scalls/accept.c b/scalls/accept.c
new file mode 100644
index 0000000..3c3f5ad
--- /dev/null
+++ b/scalls/accept.c
@@ -0,0 +1,5 @@
+#include "accept.h"
+
+int syscall_accept(SYS_ACCEPT_PARAMS *args) {
+ return accept(args->socket, args->address, args->address_len);
+}
diff --git a/scalls/accept.h b/scalls/accept.h
new file mode 100644
index 0000000..d022999
--- /dev/null
+++ b/scalls/accept.h
@@ -0,0 +1,9 @@
+#include "../socket.h"
+
+typedef struct SYS_ACCEPT_PARAMS {
+ int socket;
+ struct sockaddr *address;
+ socklen_t *address_len;
+} __attribute__((packed)) SYS_ACCEPT_PARAMS;
+
+int syscall_accept(SYS_ACCEPT_PARAMS *args);
diff --git a/scalls/bind.c b/scalls/bind.c
new file mode 100644
index 0000000..76e36ab
--- /dev/null
+++ b/scalls/bind.c
@@ -0,0 +1,5 @@
+#include "bind.h"
+
+int syscall_bind(SYS_BIND_PARAMS *args) {
+ return bind(args->sockfd, args->addr, args->addrlen);
+}
diff --git a/scalls/bind.h b/scalls/bind.h
new file mode 100644
index 0000000..5661ad0
--- /dev/null
+++ b/scalls/bind.h
@@ -0,0 +1,9 @@
+#include "../socket.h"
+
+typedef struct SYS_BIND_PARAMS {
+ int sockfd;
+ const struct sockaddr *addr;
+ socklen_t addrlen;
+} __attribute__((packed)) SYS_BIND_PARAMS;
+
+int syscall_bind(SYS_BIND_PARAMS *args);
diff --git a/scalls/clock_gettime.c b/scalls/clock_gettime.c
new file mode 100644
index 0000000..632ea08
--- /dev/null
+++ b/scalls/clock_gettime.c
@@ -0,0 +1,10 @@
+#include <scalls/clock_gettime.h>
+
+int syscall_clock_gettime(SYS_CLOCK_GETTIME_PARAMS *args) {
+ // FIXME: Actually implement this
+ if (args->ts) {
+ args->ts->tv_sec = 0;
+ args->ts->tv_nsec = 0;
+ }
+ return 0;
+}
diff --git a/scalls/clock_gettime.h b/scalls/clock_gettime.h
new file mode 100644
index 0000000..145aa24
--- /dev/null
+++ b/scalls/clock_gettime.h
@@ -0,0 +1,8 @@
+#include <time.h>
+
+typedef struct SYS_CLOCK_GETTIME_PARAMS {
+ clockid_t clk;
+ struct timespec *ts;
+} __attribute__((packed)) SYS_CLOCK_GETTIME_PARAMS;
+
+int syscall_clock_gettime(SYS_CLOCK_GETTIME_PARAMS *args);
diff --git a/scalls/mmap.c b/scalls/mmap.c
new file mode 100644
index 0000000..83fff6a
--- /dev/null
+++ b/scalls/mmap.c
@@ -0,0 +1,7 @@
+#include <scalls/mmap.h>
+#include <sched/scheduler.h>
+
+void *syscall_mmap(SYS_MMAP_PARAMS *args) {
+ return mmap(args->addr, args->length, args->prot, args->flags, args->fd,
+ args->offset);
+}
diff --git a/scalls/mmap.h b/scalls/mmap.h
new file mode 100644
index 0000000..f5e121e
--- /dev/null
+++ b/scalls/mmap.h
@@ -0,0 +1,13 @@
+#include <stddef.h>
+#include <stdint.h>
+
+typedef struct SYS_MMAP_PARAMS {
+ void *addr;
+ size_t length;
+ int prot;
+ int flags;
+ int fd;
+ size_t offset;
+} __attribute__((packed)) SYS_MMAP_PARAMS;
+
+void *syscall_mmap(SYS_MMAP_PARAMS *args);
diff --git a/scalls/msleep.c b/scalls/msleep.c
new file mode 100644
index 0000000..0120f08
--- /dev/null
+++ b/scalls/msleep.c
@@ -0,0 +1,9 @@
+#include <drivers/pit.h>
+#include <scalls/msleep.h>
+#include <sched/scheduler.h>
+#include <stdio.h>
+
+void syscall_msleep(uint32_t ms) {
+ get_current_task()->sleep_until = pit_num_ms() + ms;
+ switch_task();
+}
diff --git a/scalls/msleep.h b/scalls/msleep.h
new file mode 100644
index 0000000..71bf269
--- /dev/null
+++ b/scalls/msleep.h
@@ -0,0 +1,5 @@
+#ifndef MSLEEP_H
+#define MSLEEP_H
+#include <stdint.h>
+void syscall_msleep(uint32_t ms);
+#endif
diff --git a/scalls/ppoll.c b/scalls/ppoll.c
new file mode 100644
index 0000000..8feb35c
--- /dev/null
+++ b/scalls/ppoll.c
@@ -0,0 +1,11 @@
+#include <scalls/ppoll.h>
+#include <fs/vfs.h>
+#include <poll.h>
+#include <sched/scheduler.h>
+
+int syscall_poll(SYS_POLL_PARAMS *args) {
+ struct pollfd *fds = args->fds;
+ size_t nfds = args->nfds;
+ int timeout = args->timeout;
+ return poll(fds, nfds, timeout);
+}
diff --git a/scalls/ppoll.h b/scalls/ppoll.h
new file mode 100644
index 0000000..13700b5
--- /dev/null
+++ b/scalls/ppoll.h
@@ -0,0 +1,9 @@
+#include <stddef.h>
+
+typedef struct SYS_POLL_PARAMS {
+ struct pollfd *fds;
+ size_t nfds;
+ int timeout;
+} __attribute__((packed)) SYS_POLL_PARAMS;
+
+int syscall_poll(SYS_POLL_PARAMS *args);
diff --git a/scalls/shm.c b/scalls/shm.c
new file mode 100644
index 0000000..2e8924f
--- /dev/null
+++ b/scalls/shm.c
@@ -0,0 +1,10 @@
+#include "shm.h"
+#include "../fs/shm.h"
+
+int syscall_shm_open(SYS_SHM_OPEN_PARAMS *args) {
+ return shm_open(args->name, args->oflag, args->mode);
+}
+
+int syscall_ftruncate(SYS_FTRUNCATE_PARAMS *args) {
+ return ftruncate(args->fildes, args->length);
+}
diff --git a/scalls/shm.h b/scalls/shm.h
new file mode 100644
index 0000000..6d4e13e
--- /dev/null
+++ b/scalls/shm.h
@@ -0,0 +1,20 @@
+#ifndef SYS_SHM_H
+#define SYS_SHM_H
+#include <stddef.h>
+#include <stdint.h>
+typedef int mode_t;
+
+typedef struct SYS_SHM_OPEN_PARAMS {
+ const char *name;
+ int oflag;
+ mode_t mode;
+} __attribute__((packed)) SYS_SHM_OPEN_PARAMS;
+
+typedef struct SYS_FTRUNCATE_PARAMS {
+ int fildes;
+ uint64_t length;
+} __attribute__((packed)) SYS_FTRUNCATE_PARAMS;
+
+int syscall_shm_open(SYS_SHM_OPEN_PARAMS *args);
+int syscall_ftruncate(SYS_FTRUNCATE_PARAMS *args);
+#endif
diff --git a/scalls/socket.c b/scalls/socket.c
new file mode 100644
index 0000000..594c745
--- /dev/null
+++ b/scalls/socket.c
@@ -0,0 +1,5 @@
+#include "socket.h"
+
+int syscall_socket(SYS_SOCKET_PARAMS *args) {
+ return socket(args->domain, args->type, args->protocol);
+}
diff --git a/scalls/socket.h b/scalls/socket.h
new file mode 100644
index 0000000..6540b0f
--- /dev/null
+++ b/scalls/socket.h
@@ -0,0 +1,9 @@
+#include "../socket.h"
+
+typedef struct SYS_SOCKET_PARAMS {
+ int domain;
+ int type;
+ int protocol;
+} __attribute__((packed)) SYS_SOCKET_PARAMS;
+
+int syscall_socket(SYS_SOCKET_PARAMS *args);
diff --git a/scalls/stat.c b/scalls/stat.c
new file mode 100644
index 0000000..0850151
--- /dev/null
+++ b/scalls/stat.c
@@ -0,0 +1,13 @@
+#include <errno.h>
+#include <fs/vfs.h>
+#include <scalls/stat.h>
+
+int syscall_stat(SYS_STAT_PARAMS *args) {
+ const char *pathname = copy_and_allocate_user_string(args->pathname);
+ struct stat *statbuf = args->statbuf;
+ vfs_inode_t *i = vfs_internal_open(pathname);
+ if (!i)
+ return -ENOENT;
+ statbuf->st_size = i->file_size;
+ return 0;
+}
diff --git a/scalls/stat.h b/scalls/stat.h
new file mode 100644
index 0000000..78e8c45
--- /dev/null
+++ b/scalls/stat.h
@@ -0,0 +1,33 @@
+#include <types.h>
+#include <time.h>
+
+typedef struct SYS_STAT_PARAMS {
+ const char *pathname;
+ struct stat *statbuf;
+} __attribute__((packed)) SYS_STAT_PARAMS;
+
+struct stat {
+ dev_t st_dev; // Device ID of device containing file.
+ ino_t st_ino; // File serial number.
+ mode_t st_mode; // Mode of file (see below).
+ nlink_t st_nlink; // Number of hard links to the file.
+ uid_t st_uid; // User ID of file.
+ gid_t st_gid; // Group ID of file.
+ dev_t st_rdev; // Device ID (if file is character or block special).
+ off_t st_size; // For regular files, the file size in bytes.
+ // For symbolic links, the length in bytes of the
+ // pathname contained in the symbolic link.
+ // For a shared memory object, the length in bytes.
+ // For a typed memory object, the length in bytes.
+ // For other file types, the use of this field is
+ // unspecified.
+ struct timespec st_atim; // Last data access timestamp.
+ struct timespec st_mtim; // Last data modification timestamp.
+ struct timespec st_ctim; // Last file status change timestamp.
+ blksize_t st_blksize; // A file system-specific preferred I/O block size
+ // for this object. In some file system types, this
+ // may vary from file to file.
+ blkcnt_t st_blocks; // Number of blocks allocated for this object.
+};
+
+int syscall_stat(SYS_STAT_PARAMS *args);
diff --git a/scalls/uptime.c b/scalls/uptime.c
new file mode 100644
index 0000000..866c7e5
--- /dev/null
+++ b/scalls/uptime.c
@@ -0,0 +1,4 @@
+#include <scalls/uptime.h>
+#include <drivers/pit.h>
+
+uint32_t syscall_uptime(void) { return (uint32_t)pit_num_ms(); }
diff --git a/scalls/uptime.h b/scalls/uptime.h
new file mode 100644
index 0000000..2b5b0c9
--- /dev/null
+++ b/scalls/uptime.h
@@ -0,0 +1,2 @@
+#include <stdint.h>
+uint32_t syscall_uptime(void);
diff --git a/sched/scheduler.c b/sched/scheduler.c
new file mode 100644
index 0000000..2959693
--- /dev/null
+++ b/sched/scheduler.c
@@ -0,0 +1,388 @@
+#include <assert.h>
+#include <cpu/io.h>
+#include <defs.h>
+#include <drivers/pit.h>
+#include <elf.h>
+#include <errno.h>
+#include <fs/vfs.h>
+
+#define STACK_LOCATION ((void *)0x90000000)
+#define STACK_SIZE 0x80000
+#define HEAP_SIZE 0x400000
+#define HEAP_LOCATION (STACK_LOCATION - STACK_SIZE - HEAP_SIZE)
+
+process_t *ready_queue;
+process_t *current_task = NULL;
+uint32_t next_pid = 0;
+
+extern uint32_t read_eip(void);
+
+process_t *get_current_task(void) { return current_task; }
+
+process_t *create_process(process_t *p) {
+ process_t *r;
+ r = ksbrk(sizeof(process_t));
+ r->dead = 0;
+ r->pid = next_pid++;
+ r->esp = r->ebp = 0;
+ r->eip = 0;
+ r->sleep_until = 0;
+ if (!p) {
+ assert(1 == next_pid);
+ strncpy(r->program_name, "[kernel]", sizeof(current_task->program_name));
+ } else
+ strncpy(r->program_name, "[Not yet named]",
+ sizeof(current_task->program_name));
+
+ r->cr3 = (p) ? clone_directory(get_active_pagedirectory())
+ : get_active_pagedirectory();
+ r->next = 0;
+ r->parent = p;
+ r->child = NULL;
+ r->halt_list = NULL;
+ strcpy(r->current_working_directory, "/");
+ r->data_segment_end = (p) ? p->data_segment_end : NULL;
+ memset((void *)r->halts, 0, 2 * sizeof(uint32_t));
+ for (int i = 0; i < 100; i++) {
+ if (p) {
+ r->file_descriptors[i] = p->file_descriptors[i];
+ if (r->file_descriptors[i]) {
+ r->file_descriptors[i]->reference_count++;
+ }
+ }
+ r->read_halt_inode[i] = NULL;
+ r->write_halt_inode[i] = NULL;
+ r->disconnect_halt_inode[i] = NULL;
+ r->maps[i] = NULL;
+ }
+ return r;
+}
+
+int get_free_fd(process_t *p, int allocate) {
+ if (!p)
+ p = (process_t *)current_task;
+ int i;
+ for (i = 0; i < 100; i++)
+ if (!p->file_descriptors[i])
+ break;
+ if (p->file_descriptors[i])
+ return -1;
+ if (allocate) {
+ vfs_fd_t *fd = p->file_descriptors[i] = kmalloc(sizeof(vfs_fd_t));
+ fd->inode = kmalloc(sizeof(vfs_inode_t));
+ }
+ return i;
+}
+
+void tasking_init(void) { current_task = ready_queue = create_process(NULL); }
+
+int i = 0;
+void __attribute__((optimize("O0"))) free_process(void) {
+ kprintf("Exiting process: %s\n", get_current_task()->program_name);
+ // free_process() will purge all contents such as allocated frames
+ // out of the current process. This will be called by exit() and
+ // exec*().
+
+ // Do a special free for shared memory which avoids labeling
+ // underlying frames as "unused".
+ for (int i = 0; i < 100; i++) {
+ vfs_close(i);
+ if (!current_task->maps[i])
+ continue;
+ MemoryMap *m = current_task->maps[i];
+ mmu_remove_virtual_physical_address_mapping(m->u_address, 0x1000);
+ }
+
+ // NOTE: Kernel stuff begins at 0x90000000
+ mmu_free_address_range((void *)0x1000, 0x90000000);
+}
+
+void exit(int status) {
+ assert(current_task->pid != 1);
+ if (current_task->parent) {
+ current_task->parent->halts[WAIT_CHILD_HALT] = 0;
+ current_task->parent->child_rc = status;
+ }
+ process_t *new_task = current_task;
+ for (; new_task == current_task;) {
+ if (!new_task->next)
+ new_task = ready_queue;
+ new_task = new_task->next;
+ }
+
+ free_process();
+ // Remove current_task from list
+ for (process_t *tmp = ready_queue; tmp;) {
+ if (tmp == current_task) // current_task is ready_queue(TODO:
+ // Figure out whether this could even
+ // happen)
+ {
+ ready_queue = current_task->next;
+ break;
+ }
+ if (tmp->next == current_task) {
+ tmp->next = tmp->next->next;
+ break;
+ }
+ tmp = tmp->next;
+ }
+ current_task->dead = 1;
+ // This function will enable interrupts
+ switch_task();
+}
+
+uint32_t setup_stack(uint32_t stack_pointer, int argc, char **argv) {
+ mmu_allocate_region(STACK_LOCATION - STACK_SIZE, STACK_SIZE, MMU_FLAG_RW);
+ flush_tlb();
+
+ uint32_t ptr = stack_pointer;
+
+ char *argv_ptrs[argc + 1];
+ for (int i = 0; i < argc; i++) {
+ char *s = argv[i];
+ size_t l = strlen(s);
+ ptr -= l + 1;
+ char *b = (char *)ptr;
+ memcpy(b, s, l);
+ b[l] = '\0';
+ argv_ptrs[i] = b;
+ }
+
+ char **ptrs[argc + 1];
+ for (int i = argc; i >= 0; i--) {
+ ptr -= sizeof(char *);
+ ptrs[i] = (char **)ptr;
+ if (i != argc) {
+ *(ptrs[i]) = argv_ptrs[i];
+ } else {
+ *(ptrs[i]) = NULL;
+ }
+ }
+
+ char *s = (char *)ptr;
+ ptr -= sizeof(char **);
+ *(char ***)ptr = (char **)s;
+
+ ptr -= sizeof(int);
+ *(int *)ptr = argc;
+ return ptr;
+}
+
+int exec(const char *filename, char **argv) {
+ // exec() will "takeover" the process by loading the file specified in
+ // filename into memory, change from ring 0 to ring 3 and jump to the
+ // files entry point as decided by the ELF header of the file.
+ int argc = 0;
+ for (; argv[argc];) {
+ argc++;
+ }
+
+ uint32_t end_of_code;
+ void *entry = load_elf_file(filename, &end_of_code);
+ if (!entry) {
+ return 0;
+ }
+
+ strncpy(current_task->program_name, filename,
+ sizeof(current_task->program_name));
+
+ current_task->data_segment_end = align_page((void *)end_of_code);
+
+ uint32_t ptr = setup_stack(0x90000000, argc, argv);
+
+ jump_usermode((void (*)())(entry), ptr);
+ ASSERT_NOT_REACHED;
+ return 0;
+}
+
+int __attribute__((optimize("O0"))) fork(void) {
+ process_t *parent_task = (process_t *)current_task;
+
+ process_t *new_task = create_process(parent_task);
+
+ process_t *tmp_task = (process_t *)ready_queue;
+ for (; tmp_task->next;)
+ tmp_task = tmp_task->next;
+
+ tmp_task->next = new_task;
+
+ uint32_t eip = read_eip();
+
+ if (current_task != parent_task) {
+ return 0;
+ }
+
+ new_task->child_rc = -1;
+ new_task->parent = current_task;
+ current_task->child = new_task;
+
+ new_task->eip = eip;
+ asm("\
+ mov %%esp, %0;\
+ mov %%ebp, %1;"
+ : "=r"(new_task->esp), "=r"(new_task->ebp));
+ asm("sti");
+ return new_task->pid;
+}
+
+int is_halted(process_t *process) {
+ for (int i = 0; i < 2; i++)
+ if (process->halts[i])
+ return 1;
+
+ if (isset_fdhalt(process->read_halt_inode, process->write_halt_inode,
+ process->disconnect_halt_inode)) {
+ return 1;
+ }
+ return 0;
+}
+
+extern PageDirectory *active_directory;
+
+process_t *next_task(process_t *c) {
+ for (;;) {
+ c = c->next;
+ if (!c)
+ c = ready_queue;
+ if (c->sleep_until > pit_num_ms())
+ continue;
+ if (is_halted(c) || c->dead)
+ continue;
+ break;
+ }
+ return c;
+}
+
+int task_save_state(void) {
+ asm("mov %%esp, %0" : "=r"(current_task->esp));
+ asm("mov %%ebp, %0" : "=r"(current_task->ebp));
+
+ uint32_t eip = read_eip();
+
+ if (0x1 == eip) {
+ // Should the returned value from read_eip be equal to one it
+ // means that we have just switched over to this task after we
+ // saved the state(since the switch_task() function changes the
+ // eax register to 1).
+ return 0;
+ }
+
+ current_task->eip = eip;
+ return 1;
+}
+
+void switch_task() {
+ if (!current_task)
+ return;
+
+ if (0 == task_save_state()) {
+ return;
+ }
+
+ current_task = next_task((process_t *)current_task);
+
+ active_directory = current_task->cr3;
+
+ asm(" \
+ mov %0, %%esp; \
+ mov %1, %%ebp; \
+ mov %2, %%ecx; \
+ mov %3, %%cr3; \
+ mov $0x1, %%eax; \
+ jmp *%%ecx" ::"r"(current_task->esp),
+ "r"(current_task->ebp), "r"(current_task->eip),
+ "r"(current_task->cr3->physical_address));
+}
+
+MemoryMap **get_free_map(void) {
+ for (int i = 0; i < 100; i++)
+ if (!(current_task->maps[i]))
+ return &(current_task->maps[i]);
+ assert(0);
+ return NULL;
+}
+
+void *get_free_virtual_memory(size_t length) {
+ void *n =
+ (void *)((uintptr_t)(get_current_task()->data_segment_end) + length);
+
+ void *rc = get_current_task()->data_segment_end;
+ get_current_task()->data_segment_end = align_page(n);
+ return rc;
+}
+
+void *allocate_virtual_user_memory(size_t length, int prot, int flags) {
+ (void)prot;
+ (void)flags;
+ void *rc = get_free_virtual_memory(length);
+ if ((void *)-1 == rc)
+ return (void *)-1;
+
+ mmu_allocate_region(rc, length, MMU_FLAG_RW);
+ return rc;
+}
+
+void *user_kernel_mapping(void *kernel_addr, size_t length) {
+ void *rc = get_free_virtual_memory(length);
+ if ((void *)-1 == rc)
+ return (void *)-1;
+
+ mmu_map_directories(rc, NULL, kernel_addr, NULL, length);
+ return rc;
+}
+
+void *create_physical_mapping(void **physical_addresses, size_t length) {
+ void *rc = get_free_virtual_memory(length);
+ if ((void *)-1 == rc)
+ return (void *)-1;
+ int n = (uintptr_t)align_page((void *)length) / 0x1000;
+ for (int i = 0; i < n; i++) {
+ mmu_map_physical(rc + (i * 0x1000), NULL, physical_addresses[i], 0x1000);
+ }
+ return rc;
+}
+
+void *mmap(void *addr, size_t length, int prot, int flags, int fd,
+ size_t offset) {
+ (void)addr;
+ if (0 == length) {
+ kprintf("EINVAL\n");
+ return (void *)-EINVAL;
+ }
+
+ vfs_vm_object_t *vmobject = vfs_get_vm_object(fd, length, offset);
+ if (!vmobject) {
+ kprintf("ENODEV\n");
+ return (void *)-ENODEV;
+ }
+
+ if (vmobject->size < length) {
+ kprintf("EOVERFLOW\n");
+ return (void *)-EOVERFLOW; // TODO: Check if this is the correct
+ // code.
+ }
+
+ MemoryMap **ptr = get_free_map();
+ if (!ptr) {
+ klog("mmap(): No free memory map.", LOG_WARN);
+ return (void *)-1;
+ }
+ *ptr = kmalloc(sizeof(MemoryMap));
+ MemoryMap *free_map = *ptr;
+
+ if (fd == -1) {
+ void *rc = allocate_virtual_user_memory(length, prot, flags);
+ if ((void *)-1 == rc) {
+ kprintf("ENOMEM\n");
+ return (void *)-ENOMEM;
+ }
+ free_map->u_address = rc;
+ free_map->k_address = NULL;
+ free_map->fd = -1;
+ return rc;
+ }
+
+ if (length > vmobject->size)
+ length = vmobject->size;
+ return create_physical_mapping(vmobject->object, length);
+}
diff --git a/sched/scheduler.h b/sched/scheduler.h
new file mode 100644
index 0000000..7ff0734
--- /dev/null
+++ b/sched/scheduler.h
@@ -0,0 +1,60 @@
+#ifndef SCHEDULER_H
+#define SCHEDULER_H
+#include <fs/ext2.h>
+#include <fs/vfs.h>
+#include <halts.h>
+#include <mmu.h>
+
+#define MAX_PATH 256
+#define KEYBOARD_HALT 0
+#define WAIT_CHILD_HALT 1
+
+int fork(void);
+int exec(const char *filename, char **argv);
+void switch_task();
+void tasking_init(void);
+void exit(int status);
+
+void *mmap(void *addr, size_t length, int prot, int flags, int fd,
+ size_t offset);
+int munmap(void *addr, size_t length);
+int msync(void *addr, size_t length, int flags);
+
+typedef struct {
+ void *u_address;
+ void *k_address;
+ int fd;
+} MemoryMap;
+
+typedef struct Process process_t;
+
+struct Process {
+ uint32_t pid;
+ char program_name[100];
+ char current_working_directory[MAX_PATH];
+ uint32_t eip, esp, ebp;
+ PageDirectory *cr3;
+ vfs_fd_t *file_descriptors[100];
+ vfs_inode_t *read_halt_inode[100];
+ vfs_inode_t *write_halt_inode[100];
+ vfs_inode_t *disconnect_halt_inode[100];
+ // struct vfs_fd_t ** file_descriptors;
+ uint32_t halts[2];
+ struct Halt *halt_list;
+ void *data_segment_end;
+ // uint32_t *halts;
+ process_t *next;
+ process_t *parent;
+ process_t *child;
+ MemoryMap *maps[100];
+ uint32_t sleep_until;
+ int child_rc;
+ int dead;
+ // FIXME: Create a linkedlisti of childs so that the parent process
+ // can do stuff such as reap zombies and get status.
+};
+
+process_t *get_current_task(void);
+int get_free_fd(process_t *p, int allocate);
+void free_process(void);
+#endif
diff --git a/socket.c b/socket.c
new file mode 100644
index 0000000..0e7437c
--- /dev/null
+++ b/socket.c
@@ -0,0 +1,148 @@
+#include <errno.h>
+#include <fs/devfs.h>
+#include <fs/tmpfs.h>
+#include <poll.h>
+#include <sched/scheduler.h>
+#include <socket.h>
+
+OPEN_UNIX_SOCKET *un_sockets[100] = {0};
+
+int uds_open(const char *path) {
+ // FIXME: This is super ugly
+
+ // Find the socket that path belongs to
+ SOCKET *s = NULL;
+ for (int i = 0; i < 100; i++) {
+ if (!un_sockets[i])
+ continue;
+ const char *p = path;
+ const char *e = p;
+ for (; *e; e++)
+ ;
+ for (; e != p && *e != '/'; e--)
+ ;
+ if (0 == strcmp(e, un_sockets[i]->path)) {
+ s = un_sockets[i]->s;
+ break;
+ }
+ }
+ if (!s) {
+ return -1;
+ }
+
+ // Create a pipe
+ int fd[2];
+ dual_pipe(fd);
+
+ char c = 'i';
+ raw_vfs_pwrite(s->ptr_fifo_fd, &c, 1, 0);
+ raw_vfs_pwrite(s->ptr_socket_fd, &c, 1, 0);
+
+ s->incoming_fd = get_current_task()->file_descriptors[fd[1]];
+ // vfs_close(fd[1]);
+ return fd[0];
+}
+
+int accept(int socket, struct sockaddr *address, socklen_t *address_len) {
+ (void)address;
+ (void)address_len;
+ vfs_inode_t *inode = get_current_task()->file_descriptors[socket]->inode;
+ SOCKET *s = (SOCKET *)inode->internal_object;
+
+ if (NULL == s->incoming_fd) {
+ // Wait until we have gotten a connection
+ struct pollfd fds[1];
+ fds[0].fd = s->fifo_fd;
+ fds[0].events = POLLIN;
+ fds[0].revents = 0;
+ poll(fds, 1, 0);
+ }
+
+ int n = 0;
+ for (; get_current_task()->file_descriptors[n]; n++)
+ ;
+ get_current_task()->file_descriptors[n] = s->incoming_fd;
+ get_current_task()->file_descriptors[n]->reference_count++;
+ s->incoming_fd = NULL;
+ for (char c; 0 < vfs_pread(s->fifo_fd, &c, 1, 0);)
+ ;
+ inode->has_data = 0;
+ // s->ptr_fifo_fd->inode->has_data = 0;
+
+ return n;
+}
+
+int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
+ (void)addrlen;
+ struct sockaddr_un *un = (struct sockaddr_un *)addr;
+
+ vfs_fd_t *fd = get_vfs_fd(sockfd);
+ if (!fd)
+ return -EBADF;
+ vfs_inode_t *inode = fd->inode;
+ if (!inode)
+ return -EBADF;
+ SOCKET *s = (SOCKET *)inode->internal_object;
+
+ size_t path_len = strlen(un->sun_path);
+ s->path = kmalloc(path_len + 1);
+ memcpy(s->path, un->sun_path, path_len);
+ s->path[path_len] = '\0';
+
+ OPEN_UNIX_SOCKET *us;
+ int i = 0;
+ for (; i < 100; i++)
+ if (!un_sockets[i])
+ break;
+
+ us = un_sockets[i] = kmalloc(sizeof(OPEN_UNIX_SOCKET));
+
+ us->path = s->path;
+ us->s = s;
+ devfs_add_file(us->path, NULL, NULL, NULL, 1, 1, FS_TYPE_UNIX_SOCKET);
+ return 0;
+}
+
+int socket_write(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd) {
+ (void)buffer;
+ (void)offset;
+ fd->inode->has_data = 1;
+ return len;
+}
+
+int socket_read(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd) {
+ (void)buffer;
+ (void)offset;
+ fd->inode->has_data = 0;
+ return len;
+}
+
+void socket_close(vfs_fd_t *fd) { fd->inode->is_open = 0; }
+
+int socket(int domain, int type, int protocol) {
+ if (AF_UNIX != domain)
+ return -EINVAL;
+
+ SOCKET *new_socket = kmalloc_eternal(sizeof(SOCKET));
+ vfs_inode_t *inode = vfs_create_inode(
+ 0 /*inode_num*/, FS_TYPE_UNIX_SOCKET, 0 /*has_data*/, 1 /*can_write*/,
+ 1 /*is_open*/, new_socket /*internal_object*/, 0 /*file_size*/,
+ NULL /*open*/, NULL /*create_file*/, socket_read, socket_write,
+ socket_close, NULL /*get_vm_object*/);
+
+ vfs_fd_t *fd;
+ int n = vfs_create_fd(O_RDWR | O_NONBLOCK, 0, inode, &fd);
+
+ new_socket->domain = domain;
+ new_socket->type = type;
+ new_socket->protocol = protocol;
+ new_socket->path = NULL;
+ new_socket->incoming_fd = NULL;
+ new_socket->fifo_fd = create_fifo();
+ new_socket->ptr_fifo_fd =
+ get_current_task()->file_descriptors[new_socket->fifo_fd];
+
+ new_socket->ptr_socket_fd = fd;
+
+ return n;
+}
diff --git a/socket.h b/socket.h
new file mode 100644
index 0000000..debe29d
--- /dev/null
+++ b/socket.h
@@ -0,0 +1,66 @@
+#ifndef SOCKET_H
+#define SOCKET_H
+#include "fs/vfs.h"
+#include <stddef.h>
+#include <stdint.h>
+
+/*
+// Create a directory with the proper permissions
+mkdir(path, 0700);
+// Append the name of the socket
+strcat(path, "/socket_name");
+
+// Create the socket normally
+sockaddr_un address;
+address.sun_family = AF_UNIX;
+strcpy(address.sun_path, path);
+int fd = socket(AF_UNIX, SOCK_STREAM, 0);
+bind(fd, (sockaddr*)(&address), sizeof(address));
+listen(fd, 100);
+*/
+
+#define AF_UNIX 0
+#define AF_LOCAL AF_UNIX
+
+#define INADDR_ANY 0
+
+typedef struct {
+ int fifo_fd;
+ vfs_fd_t *ptr_fifo_fd;
+
+ vfs_fd_t *ptr_socket_fd;
+
+ int domain;
+ int type;
+ int protocol;
+
+ // UNIX socket
+ char *path;
+ vfs_fd_t *incoming_fd;
+} SOCKET;
+
+typedef struct {
+ char *path;
+ SOCKET *s;
+} OPEN_UNIX_SOCKET;
+
+typedef uint32_t in_addr_t;
+typedef uint16_t in_port_t;
+typedef unsigned int sa_family_t;
+typedef uint32_t socklen_t;
+
+struct sockaddr {
+ sa_family_t sa_family; /* Address family */
+ char *sa_data; /* Socket address */
+};
+
+struct sockaddr_un {
+ sa_family_t sun_family; /* Address family */
+ char *sun_path; /* Socket pathname */
+};
+
+int uds_open(const char *path);
+int socket(int domain, int type, int protocol);
+int accept(int socket, struct sockaddr *address, socklen_t *address_len);
+int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
+#endif
diff --git a/sync.sh b/sync.sh
new file mode 100755
index 0000000..1d94ab1
--- /dev/null
+++ b/sync.sh
@@ -0,0 +1,137 @@
+#!/bin/sh
+#pwd
+#cd /home/anton/prj/osdev/
+#cd ./userland/json/hashmap
+#make clean
+#make
+#cd ../../..
+#
+#cd ./userland/json
+#make clean
+#make
+#cd ../..
+#
+cd ./userland/libgui
+make clean
+make
+cd ../..
+#
+cd ./userland/libc
+#make clean
+make
+make install
+cd ../..
+cd ./userland/nasm-2.16.01
+#make clean
+make
+#make install
+cd ../..
+
+cd ./userland/compiler
+make
+cd ../..
+
+#cd ./userland/init
+#make clean
+#make
+#cd ../..
+#
+cd ./userland/sh
+make clean
+make
+cd ../..
+cd ./userland/sha1sum
+make clean
+make
+cd ../..
+#
+#cd ./userland/cat
+#make clean
+#make
+#cd ../..
+#
+cd ./userland/terminal
+make clean
+make
+cd ../..
+#
+cd ./userland/snake
+make clean
+make
+cd ../..
+#
+cd ./userland/ante
+make clean
+make
+cd ../..
+#
+cd ./userland/windowserver
+make clean
+make
+cd ../..
+#
+cd ./userland/test
+make clean
+make
+cd ../..
+#
+cd ./userland/minibox
+make clean
+make
+cd ../..
+
+#cd ./userland/figlet
+#cd ./userland/figlet-2.2.5/
+#make clean
+#make
+#cd ../..
+
+pwd
+sudo mount ext2.img mount
+#sudo cp ./userland/init/init ./mount/init
+#sudo cp ./userland/cat/cat ./mount/cat
+sudo cp ./userland/sh/sh ./mount/sh
+sudo cp ./userland/terminal/term ./mount/term
+sudo cp ./userland/snake/snake ./mount/snake
+sudo cp ./userland/ante/ante ./mount/ante
+sudo cp ./userland/windowserver/ws ./mount/ws
+sudo cp ./userland/test/test ./mount/test
+sudo cp ./userland/minibox/minibox ./mount/minibox
+sudo cp ./userland/nasm-2.16.01/nasm ./mount/nasm
+
+sudo cp ./userland/figlet-2.2.5/figlet ./mount/
+sudo cp ./userland/figlet-2.2.5/chkfont ./mount/
+sudo cp ./userland/figlet-2.2.5/figlist ./mount/
+sudo cp ./userland/figlet-2.2.5/showfigfonts ./mount/
+
+sudo cp ./userland/figlet-2.2.5/fonts/*.flf ./mount/fonts/
+sudo cp ./userland/figlet-2.2.5/fonts/*.flc ./mount/fonts/
+
+sudo cp ./DOOM1.WAD ./mount/DOOM1.WAD
+sudo cp ./userland/compiler/compiler ./mount/cc
+sudo cp ./userland/sha1sum/sha1sum ./mount/sha1sum
+sudo cp ./userland/sha1sum/sha1sum ./mount/sa
+sudo cp ./userland/fasm/fasm ./mount/fasm
+sudo cp ./userland/ed/ed ./mount/ed
+sudo cp ./userland/SmallerC/smlrc ./mount/sc
+sudo cp ./userland/libc/crt0.o ./mount/crt0.o
+sudo cp ./userland/libc/libc.a ./mount/libc.a
+sudo cp ./userland/doomgeneric/doomgeneric/doomgeneric ./mount/doomgeneric
+echo -e "int main(void) {\nprintf(\"hi\");\nreturn 0;\n}" > /tmp/main.c
+
+cd ./mount
+sudo rm ./init
+sudo rm ./cat
+sudo rm ./yes
+sudo rm ./echo
+sudo rm ./wc
+sudo rm ./ls
+sudo ln -s ./minibox ./init
+sudo ln -s ./minibox ./cat
+sudo ln -s ./minibox ./yes
+sudo ln -s ./minibox ./echo
+sudo ln -s ./minibox ./wc
+sudo ln -s ./minibox ./ls
+sudo cp /tmp/main.c ./main.c
+cd ..
+sudo umount mount
diff --git a/time.h b/time.h
new file mode 100644
index 0000000..2d4eef6
--- /dev/null
+++ b/time.h
@@ -0,0 +1,10 @@
+#ifndef TIME_H
+#define TIME_H
+#include <sys/types.h>
+
+typedef int clockid_t;
+struct timespec {
+ time_t tv_sec; // Seconds.
+ long tv_nsec; // Nanoseconds.
+};
+#endif
diff --git a/toolchain/3A24BC1E8FB409FA9F14371813FCEF89DD9E3C4F b/toolchain/3A24BC1E8FB409FA9F14371813FCEF89DD9E3C4F
new file mode 100644
index 0000000..b778c91
--- /dev/null
+++ b/toolchain/3A24BC1E8FB409FA9F14371813FCEF89DD9E3C4F
@@ -0,0 +1,38 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+xsFNBFm/2cUBEADkvRqMWfAryJ52T4J/640Av5cam9ojdFih9MjcX7QWFxIzJfTF
+Yq2z+nb4omdfZosdCJL2zGcn6C0AxpHNvxR9HMDkEyFHKrjDh4xWU+pH4z9azQEq
+Jh331X7UzbZldqQo16VkuVavgsTJaHcXm+nGIBTcUbl2oiTtHhmuaYxx6JTMcFjC
+7vyO5mLBw78wt52HBYweJ0NjHBvvH/JxbAAULSPRUC61K0exlO49VFbFETQNG1hZ
+TKEji95fPbre7PpXQ0ewQShUgttEE/J3UA4jYaF9lOcZgUzbA27xTV//KomP0D30
+yr4e4EJEJYYNKa3hofTEHDXeeNgM25tprhBUMdbVRZpf2Keuk2uDVwc+EiOVri48
+rb1NU+60sOXvoGO6Ks81+mhAGmrBrlgLhAp8K1HPHI4MG4gHnrMqX2rEGUGRPFjC
+3qqVVlPm8H05PnosNqDLQ1Pf7C0pVgsCx6hKQB7Y1qBui7aoj9zeFaQgpYef+CEE
+RIKEcWwrjaOJwK3pi9HFdxS0NNWYZj8HPzz/AsgTTQdsbulPlVq2SsctmOnL42CZ
+OCTppGYwl53CG/EqVY+UQBzFzJBaY8TJRFFYVEy5/HH4H11rMoZwqIkk71EOGU3X
+6mWlANRikR3M4GhVITRzuaV69Fed+OeXcCmP94ASLfuhBR2uynmcHpBKpwARAQAB
+zsFNBFm/2cUBEAC2iRP97tt607zy5IrWkyRaipMD1cpc5MJinb3dqnhBZNasrNid
+7QAkzMmFZ2E0l8uRCR9sycoVHy54S6fIyWReKFOUHoTmiT3DJsyPwmUtQJh/o55u
+qbpHWQKME8ycreCCkmqa/u5sXMV9WENl3sDJxWKS5AANnR2goS0lPxByV3t/juA4
+BFEUxTGt0kTfyeBjTAWnCl5zEkmMpSOQ3CDmf79CBmuTAFx6z9R8JtawZpaCHIJs
+3sXMwX/iHFoAi04chT337/tqXyytV2kvNjswQu30tNaQf3gzpI0ListerCmV+kbe
+e77neNLhOWtJaciLQtj+7u0Fi+Mk+aTBfqEvG5t2FoBJ7Vd/NEcmaaoCRmU2Szat
+k+GYH4mrnhFeCczpxtv0ERozlKzUGmMysuVdduwk50YOAWBf7ixJosy3CNzt1Nfp
+hM+oePMJAKIztQegGfC5vibsTluaLhnK5ExLiBuehnA8DFkvz8P7zbA8jZjgo8vX
+hCliYJjJi2qufR6X03fCDnmmMrgEBwLGLf88ystIIjII4QkLbnPfROJ0BPSmeOAy
+rJ6kWmyvbN82BNzyJAhSBGXFIiV0l1ljiHSeN4/mMhR1OYal3xAjOq8yhgXgVBk8
+8lnDl+mMETOC80A1ScGBvHFX7Yfr+PyJnF0eNw+FlccQRAIymoNNm/tcnwARAQAB
+wsFfBBgBAgAJBQJZv9nFAhsMAAoJEBP874ndnjxP3akP+gKVMILGc7abNDDnUXXY
+z8M+OKVl0uTBuOYqzEFxCxkMsZK2n3PJcB3gAWLLaCvHaaKU3CRhN3WRi9yTc9WF
+sUOQFeLsqgZ+TfEbm3APDc0eg0D/jhjyMMzJHrb1Qv3G2yg2an9Lkw8t4z+uThYU
+pExCMp2L9TG+CSZd0qvoWlG31iwFeZ26Erh5omROgc9vk43aFZDcBwX6asbujJVp
+Gvj/fElHJmPIlYT8vUAtVxThnRQxX9ZGIB1tu5hcHbN+TUITQEYH7QFc/RWV67lu
+rRSCH4rI6961Yw/UfFYC+5ebzK/cpThaXqZyOvsHdl9eeuh1uxdWcNQyK2NjRy+5
+C+et+Wx6yWOJ+6P5+xJZPwmvzAKs3SGcc+qK313iJrKmejg5+GOOz06Et0692zDT
+fTerZjj0GZCRhwwRMW4QIvyafH6VsTJqVQlJenPOXDgQkeLPLWbLxmDo0dwr6iq1
++G2/BhJa4TrwCWug3ZmV3OwMqFTGk74aat4CWCpguuKKre88CB8GgsU2z+guqFKf
+RDUVe5x51zdwZbyIAqOEBLOh5A85JoGJQhDigYg8lTEpDw2XbLKWviuBpVNksIvw
+QyTI7Q8cqPitDPNS118TnkXxCHz7Wd3XcQSj72tbkrLs/qWzfXdSWPCqOU/4derL
+rItkXlMjSRCWkp4zuc9d00NV
+=n5Jz
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/toolchain/binutils-2.40.diff b/toolchain/binutils-2.40.diff
new file mode 100644
index 0000000..e8eb8bb
--- /dev/null
+++ b/toolchain/binutils-2.40.diff
@@ -0,0 +1,12573 @@
+diff --git a/bfd/config.bfd b/bfd/config.bfd
+index 1b0111fd..369f7299 100644
+--- a/bfd/config.bfd
++++ b/bfd/config.bfd
+@@ -237,6 +237,11 @@ esac
+
+ case "${targ}" in
+ # START OF targmatch.h
++ i[3-7]86-*-sb*)
++ targ_defvec=i386_elf32_vec
++ targ_selvecs=
++ targ64_selvecs=x86_64_elf64_vec
++ ;;
+ #ifdef BFD64
+ aarch64-*-darwin*)
+ targ_defvec=aarch64_mach_o_vec
+diff --git a/config.sub b/config.sub
+index dba16e84..b30aad24 100755
+--- a/config.sub
++++ b/config.sub
+@@ -1754,7 +1754,7 @@ case $os in
+ | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \
+ | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \
+ | nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr* \
+- | fiwix* )
++ | fiwix* | sb* )
+ ;;
+ # This one is extra strict with allowed versions
+ sco3.2v2 | sco3.2v[4-9]* | sco5v6*)
+diff --git a/gas/configure.tgt b/gas/configure.tgt
+index 765ba736..85257e12 100644
+--- a/gas/configure.tgt
++++ b/gas/configure.tgt
+@@ -125,6 +125,7 @@ esac
+ generic_target=${cpu_type}-$vendor-$os
+ # Note: This table is alpha-sorted, please try to keep it that way.
+ case ${generic_target} in
++ i386-*-sb*) fmt=elf ;;
+ aarch64*-*-elf*) fmt=elf;;
+ aarch64*-*-fuchsia*) fmt=elf;;
+ aarch64*-*-haiku*) fmt=elf em=haiku ;;
+diff --git a/ld/Makefile.am b/ld/Makefile.am
+index 12b2c3c4..a9864474 100644
+--- a/ld/Makefile.am
++++ b/ld/Makefile.am
+@@ -152,6 +152,7 @@ endif
+
+ # These all start with e so 'make clean' can find them.
+ ALL_EMULATION_SOURCES = \
++ eelf_i386_sb.c \
+ eaix5ppc.c \
+ eaix5rs6.c \
+ eaixppc.c \
+@@ -770,6 +771,8 @@ $(ALL_EMULATION_SOURCES) $(ALL_64_EMULATION_SOURCES): $(GEN_DEPENDS)
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32xtensa.Pc@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32z80.Pc@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_i386.Pc@am__quote@
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_i386_sb.Pc@am__quote@
++#@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_x86_64_sb.Pc@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_i386_be.Pc@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_i386_fbsd.Pc@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_i386_haiku.Pc@am__quote@
+diff --git a/ld/Makefile.in b/ld/Makefile.in
+index 3d5685d6..b542e0e8 100644
+--- a/ld/Makefile.in
++++ b/ld/Makefile.in
+@@ -1,7 +1,7 @@
+-# Makefile.in generated by automake 1.15.1 from Makefile.am.
++# Makefile.in generated by automake 1.16.5 from Makefile.am.
+ # @configure_input@
+
+-# Copyright (C) 1994-2017 Free Software Foundation, Inc.
++# Copyright (C) 1994-2021 Free Software Foundation, Inc.
+
+ # This Makefile.in is free software; the Free Software Foundation
+ # gives unlimited permission to copy and/or distribute it,
+@@ -110,27 +110,8 @@ target_triplet = @target@
+ bin_PROGRAMS = ld-new$(EXEEXT)
+ subdir = .
+ ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+-am__aclocal_m4_deps = $(top_srcdir)/../bfd/acinclude.m4 \
+- $(top_srcdir)/../bfd/warning.m4 $(top_srcdir)/../config/acx.m4 \
+- $(top_srcdir)/../config/bfd64.m4 \
+- $(top_srcdir)/../config/depstand.m4 \
+- $(top_srcdir)/../config/enable.m4 \
+- $(top_srcdir)/../config/gettext-sister.m4 \
+- $(top_srcdir)/../config/jobserver.m4 \
+- $(top_srcdir)/../config/largefile.m4 \
+- $(top_srcdir)/../config/lcmessage.m4 \
+- $(top_srcdir)/../config/lead-dot.m4 \
+- $(top_srcdir)/../config/nls.m4 \
+- $(top_srcdir)/../config/override.m4 \
+- $(top_srcdir)/../config/pkg.m4 \
+- $(top_srcdir)/../config/plugins.m4 \
+- $(top_srcdir)/../config/po.m4 \
+- $(top_srcdir)/../config/progtest.m4 \
+- $(top_srcdir)/../config/zlib.m4 \
+- $(top_srcdir)/../config/zstd.m4 $(top_srcdir)/../libtool.m4 \
+- $(top_srcdir)/../ltoptions.m4 $(top_srcdir)/../ltsugar.m4 \
+- $(top_srcdir)/../ltversion.m4 $(top_srcdir)/../lt~obsolete.m4 \
+- $(top_srcdir)/../bfd/version.m4 $(top_srcdir)/configure.ac
++am__aclocal_m4_deps = $(top_srcdir)/../bfd/version.m4 \
++ $(top_srcdir)/configure.ac
+ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+ DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \
+@@ -141,6 +122,9 @@ mkinstalldirs = $(SHELL) $(top_srcdir)/../mkinstalldirs
+ CONFIG_HEADER = config.h
+ CONFIG_CLEAN_FILES = po/Makefile.in
+ CONFIG_CLEAN_VPATH_FILES =
++am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(bfdplugindir)" \
++ "$(DESTDIR)$(infodir)" "$(DESTDIR)$(man1dir)"
++PROGRAMS = $(bin_PROGRAMS)
+ am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+ am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+@@ -168,8 +152,6 @@ am__uninstall_files_from_dir = { \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+-am__installdirs = "$(DESTDIR)$(bfdplugindir)" "$(DESTDIR)$(bindir)" \
+- "$(DESTDIR)$(infodir)" "$(DESTDIR)$(man1dir)"
+ LTLIBRARIES = $(bfdplugin_LTLIBRARIES) $(noinst_LTLIBRARIES)
+ libdep_la_LIBADD =
+ am_libdep_la_OBJECTS = libdep_plugin.lo
+@@ -206,7 +188,6 @@ libldtestplug4_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(libldtestplug4_la_CFLAGS) $(CFLAGS) \
+ $(libldtestplug4_la_LDFLAGS) $(LDFLAGS) -o $@
+-PROGRAMS = $(bin_PROGRAMS)
+ am_ld_new_OBJECTS = ldgram.$(OBJEXT) ldlex-wrapper.$(OBJEXT) \
+ lexsup.$(OBJEXT) ldlang.$(OBJEXT) mri.$(OBJEXT) \
+ ldctor.$(OBJEXT) ldmain.$(OBJEXT) ldwrite.$(OBJEXT) \
+@@ -230,7 +211,188 @@ am__v_at_0 = @
+ am__v_at_1 =
+ DEFAULT_INCLUDES = -I.@am__isrc@
+ depcomp = $(SHELL) $(top_srcdir)/../depcomp
+-am__depfiles_maybe = depfiles
++am__maybe_remake_depfiles = depfiles
++am__depfiles_remade = ./$(DEPDIR)/deffilep.Po \
++ ./$(DEPDIR)/eaarch64cloudabi.Po \
++ ./$(DEPDIR)/eaarch64cloudabib.Po ./$(DEPDIR)/eaarch64elf.Po \
++ ./$(DEPDIR)/eaarch64elf32.Po ./$(DEPDIR)/eaarch64elf32b.Po \
++ ./$(DEPDIR)/eaarch64elfb.Po ./$(DEPDIR)/eaarch64fbsd.Po \
++ ./$(DEPDIR)/eaarch64fbsdb.Po ./$(DEPDIR)/eaarch64haiku.Po \
++ ./$(DEPDIR)/eaarch64linux.Po ./$(DEPDIR)/eaarch64linux32.Po \
++ ./$(DEPDIR)/eaarch64linux32b.Po ./$(DEPDIR)/eaarch64linuxb.Po \
++ ./$(DEPDIR)/eaarch64pe.Po ./$(DEPDIR)/eaix5ppc.Po \
++ ./$(DEPDIR)/eaix5rs6.Po ./$(DEPDIR)/eaixppc.Po \
++ ./$(DEPDIR)/eaixrs6.Po ./$(DEPDIR)/ealpha.Po \
++ ./$(DEPDIR)/ealphavms.Po ./$(DEPDIR)/earcelf.Po \
++ ./$(DEPDIR)/earclinux.Po ./$(DEPDIR)/earclinux_nps.Po \
++ ./$(DEPDIR)/earcv2elf.Po ./$(DEPDIR)/earcv2elfx.Po \
++ ./$(DEPDIR)/earm_wince_pe.Po ./$(DEPDIR)/earmelf.Po \
++ ./$(DEPDIR)/earmelf_fbsd.Po ./$(DEPDIR)/earmelf_fuchsia.Po \
++ ./$(DEPDIR)/earmelf_haiku.Po ./$(DEPDIR)/earmelf_linux.Po \
++ ./$(DEPDIR)/earmelf_linux_eabi.Po \
++ ./$(DEPDIR)/earmelf_linux_fdpiceabi.Po \
++ ./$(DEPDIR)/earmelf_nacl.Po ./$(DEPDIR)/earmelf_nbsd.Po \
++ ./$(DEPDIR)/earmelf_phoenix.Po ./$(DEPDIR)/earmelf_vxworks.Po \
++ ./$(DEPDIR)/earmelfb.Po ./$(DEPDIR)/earmelfb_fbsd.Po \
++ ./$(DEPDIR)/earmelfb_fuchsia.Po ./$(DEPDIR)/earmelfb_linux.Po \
++ ./$(DEPDIR)/earmelfb_linux_eabi.Po \
++ ./$(DEPDIR)/earmelfb_linux_fdpiceabi.Po \
++ ./$(DEPDIR)/earmelfb_nacl.Po ./$(DEPDIR)/earmelfb_nbsd.Po \
++ ./$(DEPDIR)/earmnto.Po ./$(DEPDIR)/earmpe.Po \
++ ./$(DEPDIR)/eavr1.Po ./$(DEPDIR)/eavr2.Po \
++ ./$(DEPDIR)/eavr25.Po ./$(DEPDIR)/eavr3.Po \
++ ./$(DEPDIR)/eavr31.Po ./$(DEPDIR)/eavr35.Po \
++ ./$(DEPDIR)/eavr4.Po ./$(DEPDIR)/eavr5.Po \
++ ./$(DEPDIR)/eavr51.Po ./$(DEPDIR)/eavr6.Po \
++ ./$(DEPDIR)/eavrtiny.Po ./$(DEPDIR)/eavrxmega1.Po \
++ ./$(DEPDIR)/eavrxmega2.Po ./$(DEPDIR)/eavrxmega3.Po \
++ ./$(DEPDIR)/eavrxmega4.Po ./$(DEPDIR)/eavrxmega5.Po \
++ ./$(DEPDIR)/eavrxmega6.Po ./$(DEPDIR)/eavrxmega7.Po \
++ ./$(DEPDIR)/ecrisaout.Po ./$(DEPDIR)/ecriself.Po \
++ ./$(DEPDIR)/ecrislinux.Po ./$(DEPDIR)/ecskyelf.Po \
++ ./$(DEPDIR)/ecskyelf_linux.Po ./$(DEPDIR)/ed10velf.Po \
++ ./$(DEPDIR)/ed30v_e.Po ./$(DEPDIR)/ed30v_o.Po \
++ ./$(DEPDIR)/ed30velf.Po ./$(DEPDIR)/eelf32_dlx.Po \
++ ./$(DEPDIR)/eelf32_sparc.Po ./$(DEPDIR)/eelf32_sparc_sol2.Po \
++ ./$(DEPDIR)/eelf32_sparc_vxworks.Po ./$(DEPDIR)/eelf32_spu.Po \
++ ./$(DEPDIR)/eelf32_tic6x_be.Po \
++ ./$(DEPDIR)/eelf32_tic6x_elf_be.Po \
++ ./$(DEPDIR)/eelf32_tic6x_elf_le.Po \
++ ./$(DEPDIR)/eelf32_tic6x_le.Po \
++ ./$(DEPDIR)/eelf32_tic6x_linux_be.Po \
++ ./$(DEPDIR)/eelf32_tic6x_linux_le.Po \
++ ./$(DEPDIR)/eelf32_x86_64.Po ./$(DEPDIR)/eelf32am33lin.Po \
++ ./$(DEPDIR)/eelf32b4300.Po ./$(DEPDIR)/eelf32bfin.Po \
++ ./$(DEPDIR)/eelf32bfinfd.Po ./$(DEPDIR)/eelf32bmip.Po \
++ ./$(DEPDIR)/eelf32bmipn32.Po ./$(DEPDIR)/eelf32briscv.Po \
++ ./$(DEPDIR)/eelf32briscv_ilp32.Po \
++ ./$(DEPDIR)/eelf32briscv_ilp32f.Po ./$(DEPDIR)/eelf32bsmip.Po \
++ ./$(DEPDIR)/eelf32btsmip.Po ./$(DEPDIR)/eelf32btsmip_fbsd.Po \
++ ./$(DEPDIR)/eelf32btsmipn32.Po \
++ ./$(DEPDIR)/eelf32btsmipn32_fbsd.Po ./$(DEPDIR)/eelf32cr16.Po \
++ ./$(DEPDIR)/eelf32crx.Po ./$(DEPDIR)/eelf32ebmip.Po \
++ ./$(DEPDIR)/eelf32ebmipvxworks.Po ./$(DEPDIR)/eelf32elmip.Po \
++ ./$(DEPDIR)/eelf32elmipvxworks.Po \
++ ./$(DEPDIR)/eelf32epiphany.Po \
++ ./$(DEPDIR)/eelf32epiphany_4x4.Po ./$(DEPDIR)/eelf32fr30.Po \
++ ./$(DEPDIR)/eelf32frv.Po ./$(DEPDIR)/eelf32frvfd.Po \
++ ./$(DEPDIR)/eelf32ft32.Po ./$(DEPDIR)/eelf32ip2k.Po \
++ ./$(DEPDIR)/eelf32iq10.Po ./$(DEPDIR)/eelf32iq2000.Po \
++ ./$(DEPDIR)/eelf32l4300.Po ./$(DEPDIR)/eelf32lm32.Po \
++ ./$(DEPDIR)/eelf32lm32fd.Po ./$(DEPDIR)/eelf32lmip.Po \
++ ./$(DEPDIR)/eelf32loongarch.Po ./$(DEPDIR)/eelf32lppc.Po \
++ ./$(DEPDIR)/eelf32lppclinux.Po ./$(DEPDIR)/eelf32lppcnto.Po \
++ ./$(DEPDIR)/eelf32lppcsim.Po ./$(DEPDIR)/eelf32lr5900.Po \
++ ./$(DEPDIR)/eelf32lr5900n32.Po ./$(DEPDIR)/eelf32lriscv.Po \
++ ./$(DEPDIR)/eelf32lriscv_ilp32.Po \
++ ./$(DEPDIR)/eelf32lriscv_ilp32f.Po ./$(DEPDIR)/eelf32lsmip.Po \
++ ./$(DEPDIR)/eelf32ltsmip.Po ./$(DEPDIR)/eelf32ltsmip_fbsd.Po \
++ ./$(DEPDIR)/eelf32ltsmipn32.Po \
++ ./$(DEPDIR)/eelf32ltsmipn32_fbsd.Po ./$(DEPDIR)/eelf32m32c.Po \
++ ./$(DEPDIR)/eelf32mb_linux.Po ./$(DEPDIR)/eelf32mbel_linux.Po \
++ ./$(DEPDIR)/eelf32mcore.Po ./$(DEPDIR)/eelf32mep.Po \
++ ./$(DEPDIR)/eelf32metag.Po ./$(DEPDIR)/eelf32microblaze.Po \
++ ./$(DEPDIR)/eelf32microblazeel.Po \
++ ./$(DEPDIR)/eelf32mipswindiss.Po ./$(DEPDIR)/eelf32moxie.Po \
++ ./$(DEPDIR)/eelf32mt.Po ./$(DEPDIR)/eelf32or1k.Po \
++ ./$(DEPDIR)/eelf32or1k_linux.Po ./$(DEPDIR)/eelf32ppc.Po \
++ ./$(DEPDIR)/eelf32ppc_fbsd.Po ./$(DEPDIR)/eelf32ppchaiku.Po \
++ ./$(DEPDIR)/eelf32ppclinux.Po ./$(DEPDIR)/eelf32ppcnto.Po \
++ ./$(DEPDIR)/eelf32ppcsim.Po ./$(DEPDIR)/eelf32ppcvxworks.Po \
++ ./$(DEPDIR)/eelf32ppcwindiss.Po ./$(DEPDIR)/eelf32rl78.Po \
++ ./$(DEPDIR)/eelf32rx.Po ./$(DEPDIR)/eelf32rx_linux.Po \
++ ./$(DEPDIR)/eelf32tilegx.Po ./$(DEPDIR)/eelf32tilegx_be.Po \
++ ./$(DEPDIR)/eelf32tilepro.Po ./$(DEPDIR)/eelf32vax.Po \
++ ./$(DEPDIR)/eelf32visium.Po ./$(DEPDIR)/eelf32xstormy16.Po \
++ ./$(DEPDIR)/eelf32xtensa.Po ./$(DEPDIR)/eelf32z80.Po \
++ ./$(DEPDIR)/eelf64_aix.Po ./$(DEPDIR)/eelf64_ia64.Po \
++ ./$(DEPDIR)/eelf64_ia64_fbsd.Po ./$(DEPDIR)/eelf64_ia64_vms.Po \
++ ./$(DEPDIR)/eelf64_s390.Po ./$(DEPDIR)/eelf64_sparc.Po \
++ ./$(DEPDIR)/eelf64_sparc_fbsd.Po \
++ ./$(DEPDIR)/eelf64_sparc_sol2.Po ./$(DEPDIR)/eelf64alpha.Po \
++ ./$(DEPDIR)/eelf64alpha_fbsd.Po \
++ ./$(DEPDIR)/eelf64alpha_nbsd.Po ./$(DEPDIR)/eelf64bmip.Po \
++ ./$(DEPDIR)/eelf64bpf.Po ./$(DEPDIR)/eelf64briscv.Po \
++ ./$(DEPDIR)/eelf64briscv_lp64.Po \
++ ./$(DEPDIR)/eelf64briscv_lp64f.Po ./$(DEPDIR)/eelf64btsmip.Po \
++ ./$(DEPDIR)/eelf64btsmip_fbsd.Po ./$(DEPDIR)/eelf64hppa.Po \
++ ./$(DEPDIR)/eelf64loongarch.Po ./$(DEPDIR)/eelf64lppc.Po \
++ ./$(DEPDIR)/eelf64lppc_fbsd.Po ./$(DEPDIR)/eelf64lriscv.Po \
++ ./$(DEPDIR)/eelf64lriscv_lp64.Po \
++ ./$(DEPDIR)/eelf64lriscv_lp64f.Po ./$(DEPDIR)/eelf64ltsmip.Po \
++ ./$(DEPDIR)/eelf64ltsmip_fbsd.Po ./$(DEPDIR)/eelf64mmix.Po \
++ ./$(DEPDIR)/eelf64ppc.Po ./$(DEPDIR)/eelf64ppc_fbsd.Po \
++ ./$(DEPDIR)/eelf64rdos.Po ./$(DEPDIR)/eelf64tilegx.Po \
++ ./$(DEPDIR)/eelf64tilegx_be.Po ./$(DEPDIR)/eelf_i386.Po \
++ ./$(DEPDIR)/eelf_i386_be.Po ./$(DEPDIR)/eelf_i386_fbsd.Po \
++ ./$(DEPDIR)/eelf_i386_haiku.Po ./$(DEPDIR)/eelf_i386_ldso.Po \
++ ./$(DEPDIR)/eelf_i386_sb.Po ./$(DEPDIR)/eelf_i386_sol2.Po \
++ ./$(DEPDIR)/eelf_i386_vxworks.Po ./$(DEPDIR)/eelf_iamcu.Po \
++ ./$(DEPDIR)/eelf_mipsel_haiku.Po ./$(DEPDIR)/eelf_s390.Po \
++ ./$(DEPDIR)/eelf_x86_64.Po ./$(DEPDIR)/eelf_x86_64_cloudabi.Po \
++ ./$(DEPDIR)/eelf_x86_64_fbsd.Po \
++ ./$(DEPDIR)/eelf_x86_64_haiku.Po \
++ ./$(DEPDIR)/eelf_x86_64_sol2.Po ./$(DEPDIR)/eh8300elf.Po \
++ ./$(DEPDIR)/eh8300elf_linux.Po ./$(DEPDIR)/eh8300helf.Po \
++ ./$(DEPDIR)/eh8300helf_linux.Po ./$(DEPDIR)/eh8300hnelf.Po \
++ ./$(DEPDIR)/eh8300self.Po ./$(DEPDIR)/eh8300self_linux.Po \
++ ./$(DEPDIR)/eh8300snelf.Po ./$(DEPDIR)/eh8300sxelf.Po \
++ ./$(DEPDIR)/eh8300sxelf_linux.Po ./$(DEPDIR)/eh8300sxnelf.Po \
++ ./$(DEPDIR)/ehppa64linux.Po ./$(DEPDIR)/ehppaelf.Po \
++ ./$(DEPDIR)/ehppalinux.Po ./$(DEPDIR)/ehppanbsd.Po \
++ ./$(DEPDIR)/ehppaobsd.Po ./$(DEPDIR)/ei386aout.Po \
++ ./$(DEPDIR)/ei386beos.Po ./$(DEPDIR)/ei386bsd.Po \
++ ./$(DEPDIR)/ei386go32.Po ./$(DEPDIR)/ei386lynx.Po \
++ ./$(DEPDIR)/ei386moss.Po ./$(DEPDIR)/ei386msdos.Po \
++ ./$(DEPDIR)/ei386nto.Po ./$(DEPDIR)/ei386pe.Po \
++ ./$(DEPDIR)/ei386pe_posix.Po ./$(DEPDIR)/ei386pep.Po \
++ ./$(DEPDIR)/em32relf.Po ./$(DEPDIR)/em32relf_linux.Po \
++ ./$(DEPDIR)/em32rlelf.Po ./$(DEPDIR)/em32rlelf_linux.Po \
++ ./$(DEPDIR)/em68hc11elf.Po ./$(DEPDIR)/em68hc11elfb.Po \
++ ./$(DEPDIR)/em68hc12elf.Po ./$(DEPDIR)/em68hc12elfb.Po \
++ ./$(DEPDIR)/em68kelf.Po ./$(DEPDIR)/em68kelfnbsd.Po \
++ ./$(DEPDIR)/em9s12zelf.Po ./$(DEPDIR)/emcorepe.Po \
++ ./$(DEPDIR)/emmo.Po ./$(DEPDIR)/emn10200.Po \
++ ./$(DEPDIR)/emn10300.Po ./$(DEPDIR)/emoxiebox.Po \
++ ./$(DEPDIR)/emsp430X.Po ./$(DEPDIR)/emsp430elf.Po \
++ ./$(DEPDIR)/ends32belf.Po ./$(DEPDIR)/ends32belf16m.Po \
++ ./$(DEPDIR)/ends32belf_linux.Po ./$(DEPDIR)/ends32elf.Po \
++ ./$(DEPDIR)/ends32elf16m.Po ./$(DEPDIR)/ends32elf_linux.Po \
++ ./$(DEPDIR)/enios2elf.Po ./$(DEPDIR)/enios2linux.Po \
++ ./$(DEPDIR)/ens32knbsd.Po ./$(DEPDIR)/epc532macha.Po \
++ ./$(DEPDIR)/epdp11.Po ./$(DEPDIR)/epjelf.Po \
++ ./$(DEPDIR)/epjlelf.Po ./$(DEPDIR)/eppcmacos.Po \
++ ./$(DEPDIR)/epruelf.Po ./$(DEPDIR)/escore3_elf.Po \
++ ./$(DEPDIR)/escore7_elf.Po ./$(DEPDIR)/esh.Po \
++ ./$(DEPDIR)/eshelf.Po ./$(DEPDIR)/eshelf_fd.Po \
++ ./$(DEPDIR)/eshelf_linux.Po ./$(DEPDIR)/eshelf_nbsd.Po \
++ ./$(DEPDIR)/eshelf_nto.Po ./$(DEPDIR)/eshelf_uclinux.Po \
++ ./$(DEPDIR)/eshelf_vxworks.Po ./$(DEPDIR)/eshl.Po \
++ ./$(DEPDIR)/eshlelf.Po ./$(DEPDIR)/eshlelf_fd.Po \
++ ./$(DEPDIR)/eshlelf_linux.Po ./$(DEPDIR)/eshlelf_nbsd.Po \
++ ./$(DEPDIR)/eshlelf_nto.Po ./$(DEPDIR)/eshlelf_vxworks.Po \
++ ./$(DEPDIR)/eshpe.Po ./$(DEPDIR)/etic30coff.Po \
++ ./$(DEPDIR)/etic3xcoff.Po ./$(DEPDIR)/etic3xcoff_onchip.Po \
++ ./$(DEPDIR)/etic4xcoff.Po ./$(DEPDIR)/etic54xcoff.Po \
++ ./$(DEPDIR)/ev850.Po ./$(DEPDIR)/ev850_rh850.Po \
++ ./$(DEPDIR)/evanilla.Po ./$(DEPDIR)/evaxnbsd.Po \
++ ./$(DEPDIR)/exgateelf.Po ./$(DEPDIR)/ez80.Po \
++ ./$(DEPDIR)/ez8001.Po ./$(DEPDIR)/ez8002.Po \
++ ./$(DEPDIR)/ldbuildid.Po ./$(DEPDIR)/ldcref.Po \
++ ./$(DEPDIR)/ldctor.Po ./$(DEPDIR)/ldelf.Po \
++ ./$(DEPDIR)/ldelfgen.Po ./$(DEPDIR)/ldemul.Po \
++ ./$(DEPDIR)/ldexp.Po ./$(DEPDIR)/ldfile.Po \
++ ./$(DEPDIR)/ldgram.Po ./$(DEPDIR)/ldlang.Po \
++ ./$(DEPDIR)/ldlex-wrapper.Po ./$(DEPDIR)/ldlex.Po \
++ ./$(DEPDIR)/ldmain.Po ./$(DEPDIR)/ldmisc.Po \
++ ./$(DEPDIR)/ldver.Po ./$(DEPDIR)/ldwrite.Po \
++ ./$(DEPDIR)/lexsup.Po ./$(DEPDIR)/libdep_plugin.Plo \
++ ./$(DEPDIR)/libldtestplug2_la-testplug2.Plo \
++ ./$(DEPDIR)/libldtestplug3_la-testplug3.Plo \
++ ./$(DEPDIR)/libldtestplug4_la-testplug4.Plo \
++ ./$(DEPDIR)/libldtestplug_la-testplug.Plo ./$(DEPDIR)/mri.Po \
++ ./$(DEPDIR)/pdb.Po ./$(DEPDIR)/pe-dll.Po \
++ ./$(DEPDIR)/pep-dll.Po ./$(DEPDIR)/plugin.Po
+ am__mv = mv -f
+ COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+@@ -336,8 +498,8 @@ am__recursive_targets = \
+ $(am__extra_recursive_targets)
+ AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \
+ cscope
+-am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \
+- $(LISP)config.in
++am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) \
++ config.in
+ # Read a list of newline-separated strings from the standard input,
+ # and print each of them once, without duplicates. Input order is
+ # *not* preserved.
+@@ -354,9 +516,6 @@ am__define_uniq_tagged_files = \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+-ETAGS = etags
+-CTAGS = ctags
+-CSCOPE = cscope
+ DEJATOOL = $(PACKAGE)
+ RUNTESTDEFAULTFLAGS = --tool $$tool --srcdir $$srcdir
+ DIST_SUBDIRS = $(SUBDIRS)
+@@ -369,21 +528,21 @@ AUTOCONF = @AUTOCONF@
+ AUTOHEADER = @AUTOHEADER@
+ AUTOMAKE = @AUTOMAKE@
+ AWK = @AWK@
+-CATALOGS = @CATALOGS@
+-CATOBJEXT = @CATOBJEXT@
+ CC = @CC@
+ CCDEPMODE = @CCDEPMODE@
+ CFLAGS = @CFLAGS@
+ CPP = @CPP@
+ CPPFLAGS = @CPPFLAGS@
++CSCOPE = @CSCOPE@
++CTAGS = @CTAGS@
+ CXX = @CXX@
+ CXXCPP = @CXXCPP@
+ CXXDEPMODE = @CXXDEPMODE@
+ CXXFLAGS = @CXXFLAGS@
+ CYGPATH_W = @CYGPATH_W@
+-DATADIRNAME = @DATADIRNAME@
+ DEFS = @DEFS@
+ DEPDIR = @DEPDIR@
++DLLTOOL = @DLLTOOL@
+ DSYMUTIL = @DSYMUTIL@
+ DUMPBIN = @DUMPBIN@
+ ECHO_C = @ECHO_C@
+@@ -394,29 +553,27 @@ EMUL = @EMUL@
+ EMULATION_LIBPATH = @EMULATION_LIBPATH@
+ EMULATION_OFILES = @EMULATION_OFILES@
+ EMUL_EXTRA_OFILES = @EMUL_EXTRA_OFILES@
++ETAGS = @ETAGS@
+ EXEEXT = @EXEEXT@
+ FGREP = @FGREP@
+-GENCAT = @GENCAT@
++FILECMD = @FILECMD@
++GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
+ GMSGFMT = @GMSGFMT@
++GMSGFMT_015 = @GMSGFMT_015@
+ GREP = @GREP@
+ HDEFINES = @HDEFINES@
+-INCINTL = @INCINTL@
+ INSTALL = @INSTALL@
+ INSTALL_DATA = @INSTALL_DATA@
+ INSTALL_PROGRAM = @INSTALL_PROGRAM@
+ INSTALL_SCRIPT = @INSTALL_SCRIPT@
+ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+-INSTOBJEXT = @INSTOBJEXT@
+ JANSSON_CFLAGS = @JANSSON_CFLAGS@
+ JANSSON_LIBS = @JANSSON_LIBS@
+-LARGEFILE_CPPFLAGS = @LARGEFILE_CPPFLAGS@
+ LD = @LD@
+ LDFLAGS = @LDFLAGS@
+ LEX = `if [ -f ../flex/flex ]; then echo ../flex/flex; else echo @LEX@; fi`
+ LEXLIB = @LEXLIB@
+ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+-LIBINTL = @LIBINTL@
+-LIBINTL_DEP = @LIBINTL_DEP@
+ LIBOBJS = @LIBOBJS@
+ LIBS = @LIBS@
+ LIBTOOL = @LIBTOOL@
+@@ -432,16 +589,17 @@ LIB_PATH = @LIB_PATH@
+ LIPO = @LIPO@
+ LN_S = @LN_S@
+ LTLIBOBJS = @LTLIBOBJS@
++LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+ MAINT = @MAINT@
+ MAKEINFO = @MAKEINFO@
++MANIFEST_TOOL = @MANIFEST_TOOL@
+ MKDIR_P = @MKDIR_P@
+-MKINSTALLDIRS = @MKINSTALLDIRS@
+ MSGFMT = @MSGFMT@
+ MSGMERGE = @MSGMERGE@
++MSGMERGE_FOR_MSGFMT_OPTION = @MSGMERGE_FOR_MSGFMT_OPTION@
+ NATIVE_LIB_DIRS = @NATIVE_LIB_DIRS@
+ NM = @NM@
+ NMEDIT = @NMEDIT@
+-NO_WERROR = @NO_WERROR@
+ OBJDUMP = @OBJDUMP@
+ OBJEXT = @OBJEXT@
+ OTOOL = @OTOOL@
+@@ -457,7 +615,6 @@ PATH_SEPARATOR = @PATH_SEPARATOR@
+ PKG_CONFIG = @PKG_CONFIG@
+ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+-POSUB = @POSUB@
+ RANLIB = @RANLIB@
+ SED = @SED@
+ SET_MAKE = @SET_MAKE@
+@@ -473,18 +630,16 @@ TESTCTFLIB = @TESTCTFLIB@
+ TESTSFRAMELIB = @TESTSFRAMELIB@
+ USE_NLS = @USE_NLS@
+ VERSION = @VERSION@
+-WARN_CFLAGS = @WARN_CFLAGS@
+-WARN_CFLAGS_FOR_BUILD = @WARN_CFLAGS_FOR_BUILD@
+-WARN_WRITE_STRINGS = @WARN_WRITE_STRINGS@
+ XGETTEXT = @XGETTEXT@
++XGETTEXT_015 = @XGETTEXT_015@
++XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@
+ YACC = `if [ -f ../bison/bison ]; then echo ../bison/bison -y -L$(srcdir)/../bison/; else echo @YACC@; fi`
+ YFLAGS = -d
+-ZSTD_CFLAGS = @ZSTD_CFLAGS@
+-ZSTD_LIBS = @ZSTD_LIBS@
+ abs_builddir = @abs_builddir@
+ abs_srcdir = @abs_srcdir@
+ abs_top_builddir = @abs_top_builddir@
+ abs_top_srcdir = @abs_top_srcdir@
++ac_ct_AR = @ac_ct_AR@
+ ac_ct_CC = @ac_ct_CC@
+ ac_ct_CXX = @ac_ct_CXX@
+ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+@@ -502,7 +657,6 @@ build_vendor = @build_vendor@
+ builddir = @builddir@
+ datadir = @datadir@
+ datarootdir = @datarootdir@
+-do_compare = @do_compare@
+ docdir = @docdir@
+ dvidir = @dvidir@
+ elf_list_options = @elf_list_options@
+@@ -546,8 +700,6 @@ top_build_prefix = @top_build_prefix@
+ top_builddir = @top_builddir@
+ top_srcdir = @top_srcdir@
+ use_sysroot = @use_sysroot@
+-zlibdir = @zlibdir@
+-zlibinc = @zlibinc@
+ AUTOMAKE_OPTIONS = dejagnu no-texinfo.tex no-dist foreign info-in-builddir
+ ACLOCAL_AMFLAGS = -I .. -I ../config -I ../bfd
+ TEXINFO_TEX = ../texinfo/texinfo.tex
+@@ -568,6 +720,8 @@ ELF_CLFAGS = -DELF_LIST_OPTIONS=@elf_list_options@ \
+ -DELF_SHLIB_LIST_OPTIONS=@elf_shlib_list_options@ \
+ -DELF_PLT_UNWIND_LIST_OPTIONS=@elf_plt_unwind_list_options@
+
++WARN_CFLAGS = @WARN_CFLAGS@
++NO_WERROR = @NO_WERROR@
+ AM_CFLAGS = $(WARN_CFLAGS) $(ELF_CLFAGS) $(JANSSON_CFLAGS) $(ZSTD_CFLAGS)
+
+ # We put the scripts in the directory $(scriptdir)/ldscripts.
+@@ -653,6 +807,7 @@ LIBIBERTY = ../libiberty/libiberty.a
+
+ # These all start with e so 'make clean' can find them.
+ ALL_EMULATION_SOURCES = \
++ eelf_i386_sb.c \
+ eaix5ppc.c \
+ eaix5rs6.c \
+ eaixppc.c \
+@@ -1095,8 +1250,8 @@ Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ echo ' $(SHELL) ./config.status'; \
+ $(SHELL) ./config.status;; \
+ *) \
+- echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
+- cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
++ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles)'; \
++ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles);; \
+ esac;
+
+ $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+@@ -1124,6 +1279,55 @@ distclean-hdr:
+ -rm -f config.h stamp-h1
+ po/Makefile.in: $(top_builddir)/config.status $(top_srcdir)/po/Make-in
+ cd $(top_builddir) && $(SHELL) ./config.status $@
++install-binPROGRAMS: $(bin_PROGRAMS)
++ @$(NORMAL_INSTALL)
++ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
++ if test -n "$$list"; then \
++ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \
++ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \
++ fi; \
++ for p in $$list; do echo "$$p $$p"; done | \
++ sed 's/$(EXEEXT)$$//' | \
++ while read p p1; do if test -f $$p \
++ || test -f $$p1 \
++ ; then echo "$$p"; echo "$$p"; else :; fi; \
++ done | \
++ sed -e 'p;s,.*/,,;n;h' \
++ -e 's|.*|.|' \
++ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
++ sed 'N;N;N;s,\n, ,g' | \
++ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
++ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
++ if ($$2 == $$4) files[d] = files[d] " " $$1; \
++ else { print "f", $$3 "/" $$4, $$1; } } \
++ END { for (d in files) print "f", d, files[d] }' | \
++ while read type dir files; do \
++ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
++ test -z "$$files" || { \
++ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \
++ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
++ } \
++ ; done
++
++uninstall-binPROGRAMS:
++ @$(NORMAL_UNINSTALL)
++ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
++ files=`for p in $$list; do echo "$$p"; done | \
++ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
++ -e 's/$$/$(EXEEXT)/' \
++ `; \
++ test -n "$$list" || exit 0; \
++ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
++ cd "$(DESTDIR)$(bindir)" && rm -f $$files
++
++clean-binPROGRAMS:
++ @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \
++ echo " rm -f" $$list; \
++ rm -f $$list || exit $$?; \
++ test -n "$(EXEEXT)" || exit 0; \
++ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
++ echo " rm -f" $$list; \
++ rm -f $$list
+
+ install-bfdpluginLTLIBRARIES: $(bfdplugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+@@ -1185,55 +1389,6 @@ libldtestplug3.la: $(libldtestplug3_la_OBJECTS) $(libldtestplug3_la_DEPENDENCIES
+
+ libldtestplug4.la: $(libldtestplug4_la_OBJECTS) $(libldtestplug4_la_DEPENDENCIES) $(EXTRA_libldtestplug4_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(libldtestplug4_la_LINK) $(libldtestplug4_la_OBJECTS) $(libldtestplug4_la_LIBADD) $(LIBS)
+-install-binPROGRAMS: $(bin_PROGRAMS)
+- @$(NORMAL_INSTALL)
+- @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+- if test -n "$$list"; then \
+- echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \
+- $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \
+- fi; \
+- for p in $$list; do echo "$$p $$p"; done | \
+- sed 's/$(EXEEXT)$$//' | \
+- while read p p1; do if test -f $$p \
+- || test -f $$p1 \
+- ; then echo "$$p"; echo "$$p"; else :; fi; \
+- done | \
+- sed -e 'p;s,.*/,,;n;h' \
+- -e 's|.*|.|' \
+- -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+- sed 'N;N;N;s,\n, ,g' | \
+- $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+- { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+- if ($$2 == $$4) files[d] = files[d] " " $$1; \
+- else { print "f", $$3 "/" $$4, $$1; } } \
+- END { for (d in files) print "f", d, files[d] }' | \
+- while read type dir files; do \
+- if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+- test -z "$$files" || { \
+- echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \
+- $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
+- } \
+- ; done
+-
+-uninstall-binPROGRAMS:
+- @$(NORMAL_UNINSTALL)
+- @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+- files=`for p in $$list; do echo "$$p"; done | \
+- sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+- -e 's/$$/$(EXEEXT)/' \
+- `; \
+- test -n "$$list" || exit 0; \
+- echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
+- cd "$(DESTDIR)$(bindir)" && rm -f $$files
+-
+-clean-binPROGRAMS:
+- @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \
+- echo " rm -f" $$list; \
+- rm -f $$list || exit $$?; \
+- test -n "$(EXEEXT)" || exit 0; \
+- list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+- echo " rm -f" $$list; \
+- rm -f $$list
+ ldgram.h: ldgram.c
+ @if test ! -f $@; then rm -f ldgram.c; else :; fi
+ @if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) ldgram.c; else :; fi
+@@ -1251,339 +1406,346 @@ mostlyclean-compile:
+ distclean-compile:
+ -rm -f *.tab.c
+
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/deffilep.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eaarch64cloudabi.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eaarch64cloudabib.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eaarch64elf.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eaarch64elf32.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eaarch64elf32b.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eaarch64elfb.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eaarch64fbsd.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eaarch64fbsdb.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eaarch64haiku.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eaarch64linux.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eaarch64linux32.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eaarch64linux32b.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eaarch64linuxb.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eaarch64pe.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eaix5ppc.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eaix5rs6.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eaixppc.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eaixrs6.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ealpha.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ealphavms.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earcelf.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earclinux.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earclinux_nps.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earcv2elf.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earcv2elfx.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earm_wince_pe.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earmelf.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earmelf_fbsd.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earmelf_fuchsia.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earmelf_haiku.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earmelf_linux.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earmelf_linux_eabi.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earmelf_linux_fdpiceabi.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earmelf_nacl.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earmelf_nbsd.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earmelf_phoenix.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earmelf_vxworks.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earmelfb.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earmelfb_fbsd.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earmelfb_fuchsia.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earmelfb_linux.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earmelfb_linux_eabi.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earmelfb_linux_fdpiceabi.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earmelfb_nacl.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earmelfb_nbsd.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earmnto.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earmpe.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eavr1.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eavr2.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eavr25.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eavr3.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eavr31.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eavr35.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eavr4.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eavr5.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eavr51.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eavr6.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eavrtiny.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eavrxmega1.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eavrxmega2.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eavrxmega3.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eavrxmega4.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eavrxmega5.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eavrxmega6.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eavrxmega7.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ecrisaout.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ecriself.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ecrislinux.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ecskyelf.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ecskyelf_linux.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ed10velf.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ed30v_e.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ed30v_o.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ed30velf.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32_dlx.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32_sparc.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32_sparc_sol2.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32_sparc_vxworks.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32_spu.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32_tic6x_be.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32_tic6x_elf_be.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32_tic6x_elf_le.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32_tic6x_le.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32_tic6x_linux_be.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32_tic6x_linux_le.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32_x86_64.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32am33lin.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32b4300.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32bfin.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32bfinfd.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32bmip.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32bmipn32.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32briscv.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32briscv_ilp32.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32briscv_ilp32f.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32bsmip.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32btsmip.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32btsmip_fbsd.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32btsmipn32.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32btsmipn32_fbsd.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32cr16.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32crx.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32ebmip.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32ebmipvxworks.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32elmip.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32elmipvxworks.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32epiphany.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32epiphany_4x4.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32fr30.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32frv.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32frvfd.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32ft32.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32ip2k.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32iq10.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32iq2000.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32l4300.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32lm32.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32lm32fd.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32lmip.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32loongarch.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32lppc.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32lppclinux.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32lppcnto.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32lppcsim.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32lr5900.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32lr5900n32.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32lriscv.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32lriscv_ilp32.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32lriscv_ilp32f.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32lsmip.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32ltsmip.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32ltsmip_fbsd.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32ltsmipn32.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32ltsmipn32_fbsd.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32m32c.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32mb_linux.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32mbel_linux.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32mcore.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32mep.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32metag.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32microblaze.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32microblazeel.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32mipswindiss.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32moxie.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32mt.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32or1k.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32or1k_linux.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32ppc.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32ppc_fbsd.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32ppchaiku.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32ppclinux.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32ppcnto.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32ppcsim.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32ppcvxworks.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32ppcwindiss.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32rl78.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32rx.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32rx_linux.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32tilegx.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32tilegx_be.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32tilepro.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32vax.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32visium.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32xstormy16.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32xtensa.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32z80.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64_aix.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64_ia64.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64_ia64_fbsd.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64_ia64_vms.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64_s390.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64_sparc.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64_sparc_fbsd.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64_sparc_sol2.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64alpha.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64alpha_fbsd.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64alpha_nbsd.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64bmip.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64bpf.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64briscv.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64briscv_lp64.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64briscv_lp64f.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64btsmip.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64btsmip_fbsd.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64hppa.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64loongarch.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64lppc.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64lppc_fbsd.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64lriscv.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64lriscv_lp64.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64lriscv_lp64f.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64ltsmip.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64ltsmip_fbsd.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64mmix.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64ppc.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64ppc_fbsd.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64rdos.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64tilegx.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64tilegx_be.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_i386.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_i386_be.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_i386_fbsd.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_i386_haiku.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_i386_ldso.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_i386_sol2.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_i386_vxworks.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_iamcu.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_mipsel_haiku.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_s390.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_x86_64.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_x86_64_cloudabi.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_x86_64_fbsd.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_x86_64_haiku.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_x86_64_sol2.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eh8300elf.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eh8300elf_linux.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eh8300helf.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eh8300helf_linux.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eh8300hnelf.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eh8300self.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eh8300self_linux.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eh8300snelf.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eh8300sxelf.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eh8300sxelf_linux.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eh8300sxnelf.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ehppa64linux.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ehppaelf.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ehppalinux.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ehppanbsd.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ehppaobsd.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ei386aout.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ei386beos.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ei386bsd.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ei386go32.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ei386lynx.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ei386moss.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ei386msdos.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ei386nto.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ei386pe.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ei386pe_posix.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ei386pep.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/em32relf.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/em32relf_linux.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/em32rlelf.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/em32rlelf_linux.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/em68hc11elf.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/em68hc11elfb.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/em68hc12elf.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/em68hc12elfb.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/em68kelf.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/em68kelfnbsd.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/em9s12zelf.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emcorepe.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emmo.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emn10200.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emn10300.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emoxiebox.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430X.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430elf.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ends32belf.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ends32belf16m.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ends32belf_linux.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ends32elf.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ends32elf16m.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ends32elf_linux.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/enios2elf.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/enios2linux.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ens32knbsd.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/epc532macha.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/epdp11.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/epjelf.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/epjlelf.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eppcmacos.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/epruelf.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/escore3_elf.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/escore7_elf.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/esh.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eshelf.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eshelf_fd.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eshelf_linux.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eshelf_nbsd.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eshelf_nto.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eshelf_uclinux.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eshelf_vxworks.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eshl.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eshlelf.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eshlelf_fd.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eshlelf_linux.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eshlelf_nbsd.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eshlelf_nto.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eshlelf_vxworks.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eshpe.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/etic30coff.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/etic3xcoff.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/etic3xcoff_onchip.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/etic4xcoff.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/etic54xcoff.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ev850.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ev850_rh850.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/evanilla.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/evaxnbsd.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exgateelf.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ez80.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ez8001.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ez8002.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ldbuildid.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ldcref.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ldctor.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ldelf.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ldelfgen.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ldemul.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ldexp.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ldfile.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ldgram.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ldlang.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ldlex-wrapper.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ldlex.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ldmain.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ldmisc.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ldver.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ldwrite.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lexsup.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdep_plugin.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libldtestplug2_la-testplug2.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libldtestplug3_la-testplug3.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libldtestplug4_la-testplug4.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libldtestplug_la-testplug.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mri.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pdb.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pe-dll.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pep-dll.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin.Po@am__quote@
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/deffilep.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eaarch64cloudabi.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eaarch64cloudabib.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eaarch64elf.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eaarch64elf32.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eaarch64elf32b.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eaarch64elfb.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eaarch64fbsd.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eaarch64fbsdb.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eaarch64haiku.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eaarch64linux.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eaarch64linux32.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eaarch64linux32b.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eaarch64linuxb.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eaarch64pe.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eaix5ppc.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eaix5rs6.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eaixppc.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eaixrs6.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ealpha.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ealphavms.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earcelf.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earclinux.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earclinux_nps.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earcv2elf.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earcv2elfx.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earm_wince_pe.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earmelf.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earmelf_fbsd.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earmelf_fuchsia.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earmelf_haiku.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earmelf_linux.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earmelf_linux_eabi.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earmelf_linux_fdpiceabi.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earmelf_nacl.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earmelf_nbsd.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earmelf_phoenix.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earmelf_vxworks.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earmelfb.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earmelfb_fbsd.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earmelfb_fuchsia.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earmelfb_linux.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earmelfb_linux_eabi.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earmelfb_linux_fdpiceabi.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earmelfb_nacl.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earmelfb_nbsd.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earmnto.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earmpe.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eavr1.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eavr2.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eavr25.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eavr3.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eavr31.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eavr35.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eavr4.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eavr5.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eavr51.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eavr6.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eavrtiny.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eavrxmega1.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eavrxmega2.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eavrxmega3.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eavrxmega4.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eavrxmega5.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eavrxmega6.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eavrxmega7.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ecrisaout.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ecriself.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ecrislinux.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ecskyelf.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ecskyelf_linux.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ed10velf.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ed30v_e.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ed30v_o.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ed30velf.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32_dlx.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32_sparc.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32_sparc_sol2.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32_sparc_vxworks.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32_spu.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32_tic6x_be.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32_tic6x_elf_be.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32_tic6x_elf_le.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32_tic6x_le.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32_tic6x_linux_be.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32_tic6x_linux_le.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32_x86_64.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32am33lin.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32b4300.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32bfin.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32bfinfd.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32bmip.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32bmipn32.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32briscv.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32briscv_ilp32.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32briscv_ilp32f.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32bsmip.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32btsmip.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32btsmip_fbsd.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32btsmipn32.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32btsmipn32_fbsd.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32cr16.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32crx.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32ebmip.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32ebmipvxworks.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32elmip.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32elmipvxworks.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32epiphany.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32epiphany_4x4.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32fr30.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32frv.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32frvfd.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32ft32.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32ip2k.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32iq10.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32iq2000.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32l4300.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32lm32.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32lm32fd.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32lmip.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32loongarch.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32lppc.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32lppclinux.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32lppcnto.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32lppcsim.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32lr5900.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32lr5900n32.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32lriscv.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32lriscv_ilp32.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32lriscv_ilp32f.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32lsmip.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32ltsmip.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32ltsmip_fbsd.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32ltsmipn32.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32ltsmipn32_fbsd.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32m32c.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32mb_linux.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32mbel_linux.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32mcore.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32mep.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32metag.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32microblaze.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32microblazeel.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32mipswindiss.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32moxie.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32mt.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32or1k.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32or1k_linux.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32ppc.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32ppc_fbsd.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32ppchaiku.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32ppclinux.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32ppcnto.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32ppcsim.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32ppcvxworks.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32ppcwindiss.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32rl78.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32rx.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32rx_linux.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32tilegx.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32tilegx_be.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32tilepro.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32vax.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32visium.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32xstormy16.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32xtensa.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32z80.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64_aix.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64_ia64.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64_ia64_fbsd.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64_ia64_vms.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64_s390.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64_sparc.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64_sparc_fbsd.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64_sparc_sol2.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64alpha.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64alpha_fbsd.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64alpha_nbsd.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64bmip.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64bpf.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64briscv.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64briscv_lp64.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64briscv_lp64f.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64btsmip.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64btsmip_fbsd.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64hppa.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64loongarch.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64lppc.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64lppc_fbsd.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64lriscv.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64lriscv_lp64.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64lriscv_lp64f.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64ltsmip.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64ltsmip_fbsd.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64mmix.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64ppc.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64ppc_fbsd.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64rdos.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64tilegx.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64tilegx_be.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_i386.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_i386_be.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_i386_fbsd.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_i386_haiku.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_i386_ldso.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_i386_sb.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_i386_sol2.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_i386_vxworks.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_iamcu.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_mipsel_haiku.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_s390.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_x86_64.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_x86_64_cloudabi.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_x86_64_fbsd.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_x86_64_haiku.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_x86_64_sol2.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eh8300elf.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eh8300elf_linux.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eh8300helf.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eh8300helf_linux.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eh8300hnelf.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eh8300self.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eh8300self_linux.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eh8300snelf.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eh8300sxelf.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eh8300sxelf_linux.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eh8300sxnelf.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ehppa64linux.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ehppaelf.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ehppalinux.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ehppanbsd.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ehppaobsd.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ei386aout.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ei386beos.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ei386bsd.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ei386go32.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ei386lynx.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ei386moss.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ei386msdos.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ei386nto.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ei386pe.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ei386pe_posix.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ei386pep.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/em32relf.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/em32relf_linux.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/em32rlelf.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/em32rlelf_linux.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/em68hc11elf.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/em68hc11elfb.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/em68hc12elf.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/em68hc12elfb.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/em68kelf.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/em68kelfnbsd.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/em9s12zelf.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emcorepe.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emmo.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emn10200.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emn10300.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emoxiebox.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430X.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430elf.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ends32belf.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ends32belf16m.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ends32belf_linux.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ends32elf.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ends32elf16m.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ends32elf_linux.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/enios2elf.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/enios2linux.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ens32knbsd.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/epc532macha.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/epdp11.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/epjelf.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/epjlelf.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eppcmacos.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/epruelf.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/escore3_elf.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/escore7_elf.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/esh.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eshelf.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eshelf_fd.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eshelf_linux.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eshelf_nbsd.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eshelf_nto.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eshelf_uclinux.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eshelf_vxworks.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eshl.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eshlelf.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eshlelf_fd.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eshlelf_linux.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eshlelf_nbsd.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eshlelf_nto.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eshlelf_vxworks.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eshpe.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/etic30coff.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/etic3xcoff.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/etic3xcoff_onchip.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/etic4xcoff.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/etic54xcoff.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ev850.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ev850_rh850.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/evanilla.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/evaxnbsd.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exgateelf.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ez80.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ez8001.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ez8002.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ldbuildid.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ldcref.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ldctor.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ldelf.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ldelfgen.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ldemul.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ldexp.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ldfile.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ldgram.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ldlang.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ldlex-wrapper.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ldlex.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ldmain.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ldmisc.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ldver.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ldwrite.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lexsup.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdep_plugin.Plo@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libldtestplug2_la-testplug2.Plo@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libldtestplug3_la-testplug3.Plo@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libldtestplug4_la-testplug4.Plo@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libldtestplug_la-testplug.Plo@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mri.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pdb.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pe-dll.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pep-dll.Po@am__quote@ # am--include-marker
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin.Po@am__quote@ # am--include-marker
++
++$(am__depfiles_remade):
++ @$(MKDIR_P) $(@D)
++ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
++
++am--depfiles: $(am__depfiles_remade)
+
+ .c.o:
+ @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@@ -1936,7 +2098,7 @@ site.exp: Makefile $(EXTRA_DEJAGNU_SITE_CONFIG)
+ @echo '# Do not edit here. If you wish to override these values' >>site.tmp
+ @echo '# edit the last section' >>site.tmp
+ @echo 'set srcdir "$(srcdir)"' >>site.tmp
+- @echo "set objdir `pwd`" >>site.tmp
++ @echo "set objdir \"`pwd`\"" >>site.tmp
+ @echo 'set build_alias "$(build_alias)"' >>site.tmp
+ @echo 'set build_triplet $(build_triplet)' >>site.tmp
+ @echo 'set host_alias "$(host_alias)"' >>site.tmp
+@@ -1966,16 +2128,17 @@ check-am: all-am
+ $(MAKE) $(AM_MAKEFLAGS) check-DEJAGNU
+ check: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) check-recursive
+-all-am: Makefile $(INFO_DEPS) $(LTLIBRARIES) $(PROGRAMS) $(MANS) \
++all-am: Makefile $(INFO_DEPS) $(PROGRAMS) $(LTLIBRARIES) $(MANS) \
+ config.h
+ installdirs: installdirs-recursive
+ installdirs-am:
+- for dir in "$(DESTDIR)$(bfdplugindir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(infodir)" "$(DESTDIR)$(man1dir)"; do \
++ for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(bfdplugindir)" "$(DESTDIR)$(infodir)" "$(DESTDIR)$(man1dir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+ install: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) install-recursive
+-install-exec: install-exec-recursive
++install-exec: $(BUILT_SOURCES)
++ $(MAKE) $(AM_MAKEFLAGS) install-exec-recursive
+ install-data: install-data-recursive
+ uninstall: uninstall-recursive
+
+@@ -2022,7 +2185,340 @@ clean-am: clean-aminfo clean-bfdpluginLTLIBRARIES clean-binPROGRAMS \
+
+ distclean: distclean-recursive
+ -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+- -rm -rf ./$(DEPDIR)
++ -rm -f ./$(DEPDIR)/deffilep.Po
++ -rm -f ./$(DEPDIR)/eaarch64cloudabi.Po
++ -rm -f ./$(DEPDIR)/eaarch64cloudabib.Po
++ -rm -f ./$(DEPDIR)/eaarch64elf.Po
++ -rm -f ./$(DEPDIR)/eaarch64elf32.Po
++ -rm -f ./$(DEPDIR)/eaarch64elf32b.Po
++ -rm -f ./$(DEPDIR)/eaarch64elfb.Po
++ -rm -f ./$(DEPDIR)/eaarch64fbsd.Po
++ -rm -f ./$(DEPDIR)/eaarch64fbsdb.Po
++ -rm -f ./$(DEPDIR)/eaarch64haiku.Po
++ -rm -f ./$(DEPDIR)/eaarch64linux.Po
++ -rm -f ./$(DEPDIR)/eaarch64linux32.Po
++ -rm -f ./$(DEPDIR)/eaarch64linux32b.Po
++ -rm -f ./$(DEPDIR)/eaarch64linuxb.Po
++ -rm -f ./$(DEPDIR)/eaarch64pe.Po
++ -rm -f ./$(DEPDIR)/eaix5ppc.Po
++ -rm -f ./$(DEPDIR)/eaix5rs6.Po
++ -rm -f ./$(DEPDIR)/eaixppc.Po
++ -rm -f ./$(DEPDIR)/eaixrs6.Po
++ -rm -f ./$(DEPDIR)/ealpha.Po
++ -rm -f ./$(DEPDIR)/ealphavms.Po
++ -rm -f ./$(DEPDIR)/earcelf.Po
++ -rm -f ./$(DEPDIR)/earclinux.Po
++ -rm -f ./$(DEPDIR)/earclinux_nps.Po
++ -rm -f ./$(DEPDIR)/earcv2elf.Po
++ -rm -f ./$(DEPDIR)/earcv2elfx.Po
++ -rm -f ./$(DEPDIR)/earm_wince_pe.Po
++ -rm -f ./$(DEPDIR)/earmelf.Po
++ -rm -f ./$(DEPDIR)/earmelf_fbsd.Po
++ -rm -f ./$(DEPDIR)/earmelf_fuchsia.Po
++ -rm -f ./$(DEPDIR)/earmelf_haiku.Po
++ -rm -f ./$(DEPDIR)/earmelf_linux.Po
++ -rm -f ./$(DEPDIR)/earmelf_linux_eabi.Po
++ -rm -f ./$(DEPDIR)/earmelf_linux_fdpiceabi.Po
++ -rm -f ./$(DEPDIR)/earmelf_nacl.Po
++ -rm -f ./$(DEPDIR)/earmelf_nbsd.Po
++ -rm -f ./$(DEPDIR)/earmelf_phoenix.Po
++ -rm -f ./$(DEPDIR)/earmelf_vxworks.Po
++ -rm -f ./$(DEPDIR)/earmelfb.Po
++ -rm -f ./$(DEPDIR)/earmelfb_fbsd.Po
++ -rm -f ./$(DEPDIR)/earmelfb_fuchsia.Po
++ -rm -f ./$(DEPDIR)/earmelfb_linux.Po
++ -rm -f ./$(DEPDIR)/earmelfb_linux_eabi.Po
++ -rm -f ./$(DEPDIR)/earmelfb_linux_fdpiceabi.Po
++ -rm -f ./$(DEPDIR)/earmelfb_nacl.Po
++ -rm -f ./$(DEPDIR)/earmelfb_nbsd.Po
++ -rm -f ./$(DEPDIR)/earmnto.Po
++ -rm -f ./$(DEPDIR)/earmpe.Po
++ -rm -f ./$(DEPDIR)/eavr1.Po
++ -rm -f ./$(DEPDIR)/eavr2.Po
++ -rm -f ./$(DEPDIR)/eavr25.Po
++ -rm -f ./$(DEPDIR)/eavr3.Po
++ -rm -f ./$(DEPDIR)/eavr31.Po
++ -rm -f ./$(DEPDIR)/eavr35.Po
++ -rm -f ./$(DEPDIR)/eavr4.Po
++ -rm -f ./$(DEPDIR)/eavr5.Po
++ -rm -f ./$(DEPDIR)/eavr51.Po
++ -rm -f ./$(DEPDIR)/eavr6.Po
++ -rm -f ./$(DEPDIR)/eavrtiny.Po
++ -rm -f ./$(DEPDIR)/eavrxmega1.Po
++ -rm -f ./$(DEPDIR)/eavrxmega2.Po
++ -rm -f ./$(DEPDIR)/eavrxmega3.Po
++ -rm -f ./$(DEPDIR)/eavrxmega4.Po
++ -rm -f ./$(DEPDIR)/eavrxmega5.Po
++ -rm -f ./$(DEPDIR)/eavrxmega6.Po
++ -rm -f ./$(DEPDIR)/eavrxmega7.Po
++ -rm -f ./$(DEPDIR)/ecrisaout.Po
++ -rm -f ./$(DEPDIR)/ecriself.Po
++ -rm -f ./$(DEPDIR)/ecrislinux.Po
++ -rm -f ./$(DEPDIR)/ecskyelf.Po
++ -rm -f ./$(DEPDIR)/ecskyelf_linux.Po
++ -rm -f ./$(DEPDIR)/ed10velf.Po
++ -rm -f ./$(DEPDIR)/ed30v_e.Po
++ -rm -f ./$(DEPDIR)/ed30v_o.Po
++ -rm -f ./$(DEPDIR)/ed30velf.Po
++ -rm -f ./$(DEPDIR)/eelf32_dlx.Po
++ -rm -f ./$(DEPDIR)/eelf32_sparc.Po
++ -rm -f ./$(DEPDIR)/eelf32_sparc_sol2.Po
++ -rm -f ./$(DEPDIR)/eelf32_sparc_vxworks.Po
++ -rm -f ./$(DEPDIR)/eelf32_spu.Po
++ -rm -f ./$(DEPDIR)/eelf32_tic6x_be.Po
++ -rm -f ./$(DEPDIR)/eelf32_tic6x_elf_be.Po
++ -rm -f ./$(DEPDIR)/eelf32_tic6x_elf_le.Po
++ -rm -f ./$(DEPDIR)/eelf32_tic6x_le.Po
++ -rm -f ./$(DEPDIR)/eelf32_tic6x_linux_be.Po
++ -rm -f ./$(DEPDIR)/eelf32_tic6x_linux_le.Po
++ -rm -f ./$(DEPDIR)/eelf32_x86_64.Po
++ -rm -f ./$(DEPDIR)/eelf32am33lin.Po
++ -rm -f ./$(DEPDIR)/eelf32b4300.Po
++ -rm -f ./$(DEPDIR)/eelf32bfin.Po
++ -rm -f ./$(DEPDIR)/eelf32bfinfd.Po
++ -rm -f ./$(DEPDIR)/eelf32bmip.Po
++ -rm -f ./$(DEPDIR)/eelf32bmipn32.Po
++ -rm -f ./$(DEPDIR)/eelf32briscv.Po
++ -rm -f ./$(DEPDIR)/eelf32briscv_ilp32.Po
++ -rm -f ./$(DEPDIR)/eelf32briscv_ilp32f.Po
++ -rm -f ./$(DEPDIR)/eelf32bsmip.Po
++ -rm -f ./$(DEPDIR)/eelf32btsmip.Po
++ -rm -f ./$(DEPDIR)/eelf32btsmip_fbsd.Po
++ -rm -f ./$(DEPDIR)/eelf32btsmipn32.Po
++ -rm -f ./$(DEPDIR)/eelf32btsmipn32_fbsd.Po
++ -rm -f ./$(DEPDIR)/eelf32cr16.Po
++ -rm -f ./$(DEPDIR)/eelf32crx.Po
++ -rm -f ./$(DEPDIR)/eelf32ebmip.Po
++ -rm -f ./$(DEPDIR)/eelf32ebmipvxworks.Po
++ -rm -f ./$(DEPDIR)/eelf32elmip.Po
++ -rm -f ./$(DEPDIR)/eelf32elmipvxworks.Po
++ -rm -f ./$(DEPDIR)/eelf32epiphany.Po
++ -rm -f ./$(DEPDIR)/eelf32epiphany_4x4.Po
++ -rm -f ./$(DEPDIR)/eelf32fr30.Po
++ -rm -f ./$(DEPDIR)/eelf32frv.Po
++ -rm -f ./$(DEPDIR)/eelf32frvfd.Po
++ -rm -f ./$(DEPDIR)/eelf32ft32.Po
++ -rm -f ./$(DEPDIR)/eelf32ip2k.Po
++ -rm -f ./$(DEPDIR)/eelf32iq10.Po
++ -rm -f ./$(DEPDIR)/eelf32iq2000.Po
++ -rm -f ./$(DEPDIR)/eelf32l4300.Po
++ -rm -f ./$(DEPDIR)/eelf32lm32.Po
++ -rm -f ./$(DEPDIR)/eelf32lm32fd.Po
++ -rm -f ./$(DEPDIR)/eelf32lmip.Po
++ -rm -f ./$(DEPDIR)/eelf32loongarch.Po
++ -rm -f ./$(DEPDIR)/eelf32lppc.Po
++ -rm -f ./$(DEPDIR)/eelf32lppclinux.Po
++ -rm -f ./$(DEPDIR)/eelf32lppcnto.Po
++ -rm -f ./$(DEPDIR)/eelf32lppcsim.Po
++ -rm -f ./$(DEPDIR)/eelf32lr5900.Po
++ -rm -f ./$(DEPDIR)/eelf32lr5900n32.Po
++ -rm -f ./$(DEPDIR)/eelf32lriscv.Po
++ -rm -f ./$(DEPDIR)/eelf32lriscv_ilp32.Po
++ -rm -f ./$(DEPDIR)/eelf32lriscv_ilp32f.Po
++ -rm -f ./$(DEPDIR)/eelf32lsmip.Po
++ -rm -f ./$(DEPDIR)/eelf32ltsmip.Po
++ -rm -f ./$(DEPDIR)/eelf32ltsmip_fbsd.Po
++ -rm -f ./$(DEPDIR)/eelf32ltsmipn32.Po
++ -rm -f ./$(DEPDIR)/eelf32ltsmipn32_fbsd.Po
++ -rm -f ./$(DEPDIR)/eelf32m32c.Po
++ -rm -f ./$(DEPDIR)/eelf32mb_linux.Po
++ -rm -f ./$(DEPDIR)/eelf32mbel_linux.Po
++ -rm -f ./$(DEPDIR)/eelf32mcore.Po
++ -rm -f ./$(DEPDIR)/eelf32mep.Po
++ -rm -f ./$(DEPDIR)/eelf32metag.Po
++ -rm -f ./$(DEPDIR)/eelf32microblaze.Po
++ -rm -f ./$(DEPDIR)/eelf32microblazeel.Po
++ -rm -f ./$(DEPDIR)/eelf32mipswindiss.Po
++ -rm -f ./$(DEPDIR)/eelf32moxie.Po
++ -rm -f ./$(DEPDIR)/eelf32mt.Po
++ -rm -f ./$(DEPDIR)/eelf32or1k.Po
++ -rm -f ./$(DEPDIR)/eelf32or1k_linux.Po
++ -rm -f ./$(DEPDIR)/eelf32ppc.Po
++ -rm -f ./$(DEPDIR)/eelf32ppc_fbsd.Po
++ -rm -f ./$(DEPDIR)/eelf32ppchaiku.Po
++ -rm -f ./$(DEPDIR)/eelf32ppclinux.Po
++ -rm -f ./$(DEPDIR)/eelf32ppcnto.Po
++ -rm -f ./$(DEPDIR)/eelf32ppcsim.Po
++ -rm -f ./$(DEPDIR)/eelf32ppcvxworks.Po
++ -rm -f ./$(DEPDIR)/eelf32ppcwindiss.Po
++ -rm -f ./$(DEPDIR)/eelf32rl78.Po
++ -rm -f ./$(DEPDIR)/eelf32rx.Po
++ -rm -f ./$(DEPDIR)/eelf32rx_linux.Po
++ -rm -f ./$(DEPDIR)/eelf32tilegx.Po
++ -rm -f ./$(DEPDIR)/eelf32tilegx_be.Po
++ -rm -f ./$(DEPDIR)/eelf32tilepro.Po
++ -rm -f ./$(DEPDIR)/eelf32vax.Po
++ -rm -f ./$(DEPDIR)/eelf32visium.Po
++ -rm -f ./$(DEPDIR)/eelf32xstormy16.Po
++ -rm -f ./$(DEPDIR)/eelf32xtensa.Po
++ -rm -f ./$(DEPDIR)/eelf32z80.Po
++ -rm -f ./$(DEPDIR)/eelf64_aix.Po
++ -rm -f ./$(DEPDIR)/eelf64_ia64.Po
++ -rm -f ./$(DEPDIR)/eelf64_ia64_fbsd.Po
++ -rm -f ./$(DEPDIR)/eelf64_ia64_vms.Po
++ -rm -f ./$(DEPDIR)/eelf64_s390.Po
++ -rm -f ./$(DEPDIR)/eelf64_sparc.Po
++ -rm -f ./$(DEPDIR)/eelf64_sparc_fbsd.Po
++ -rm -f ./$(DEPDIR)/eelf64_sparc_sol2.Po
++ -rm -f ./$(DEPDIR)/eelf64alpha.Po
++ -rm -f ./$(DEPDIR)/eelf64alpha_fbsd.Po
++ -rm -f ./$(DEPDIR)/eelf64alpha_nbsd.Po
++ -rm -f ./$(DEPDIR)/eelf64bmip.Po
++ -rm -f ./$(DEPDIR)/eelf64bpf.Po
++ -rm -f ./$(DEPDIR)/eelf64briscv.Po
++ -rm -f ./$(DEPDIR)/eelf64briscv_lp64.Po
++ -rm -f ./$(DEPDIR)/eelf64briscv_lp64f.Po
++ -rm -f ./$(DEPDIR)/eelf64btsmip.Po
++ -rm -f ./$(DEPDIR)/eelf64btsmip_fbsd.Po
++ -rm -f ./$(DEPDIR)/eelf64hppa.Po
++ -rm -f ./$(DEPDIR)/eelf64loongarch.Po
++ -rm -f ./$(DEPDIR)/eelf64lppc.Po
++ -rm -f ./$(DEPDIR)/eelf64lppc_fbsd.Po
++ -rm -f ./$(DEPDIR)/eelf64lriscv.Po
++ -rm -f ./$(DEPDIR)/eelf64lriscv_lp64.Po
++ -rm -f ./$(DEPDIR)/eelf64lriscv_lp64f.Po
++ -rm -f ./$(DEPDIR)/eelf64ltsmip.Po
++ -rm -f ./$(DEPDIR)/eelf64ltsmip_fbsd.Po
++ -rm -f ./$(DEPDIR)/eelf64mmix.Po
++ -rm -f ./$(DEPDIR)/eelf64ppc.Po
++ -rm -f ./$(DEPDIR)/eelf64ppc_fbsd.Po
++ -rm -f ./$(DEPDIR)/eelf64rdos.Po
++ -rm -f ./$(DEPDIR)/eelf64tilegx.Po
++ -rm -f ./$(DEPDIR)/eelf64tilegx_be.Po
++ -rm -f ./$(DEPDIR)/eelf_i386.Po
++ -rm -f ./$(DEPDIR)/eelf_i386_be.Po
++ -rm -f ./$(DEPDIR)/eelf_i386_fbsd.Po
++ -rm -f ./$(DEPDIR)/eelf_i386_haiku.Po
++ -rm -f ./$(DEPDIR)/eelf_i386_ldso.Po
++ -rm -f ./$(DEPDIR)/eelf_i386_sb.Po
++ -rm -f ./$(DEPDIR)/eelf_i386_sol2.Po
++ -rm -f ./$(DEPDIR)/eelf_i386_vxworks.Po
++ -rm -f ./$(DEPDIR)/eelf_iamcu.Po
++ -rm -f ./$(DEPDIR)/eelf_mipsel_haiku.Po
++ -rm -f ./$(DEPDIR)/eelf_s390.Po
++ -rm -f ./$(DEPDIR)/eelf_x86_64.Po
++ -rm -f ./$(DEPDIR)/eelf_x86_64_cloudabi.Po
++ -rm -f ./$(DEPDIR)/eelf_x86_64_fbsd.Po
++ -rm -f ./$(DEPDIR)/eelf_x86_64_haiku.Po
++ -rm -f ./$(DEPDIR)/eelf_x86_64_sol2.Po
++ -rm -f ./$(DEPDIR)/eh8300elf.Po
++ -rm -f ./$(DEPDIR)/eh8300elf_linux.Po
++ -rm -f ./$(DEPDIR)/eh8300helf.Po
++ -rm -f ./$(DEPDIR)/eh8300helf_linux.Po
++ -rm -f ./$(DEPDIR)/eh8300hnelf.Po
++ -rm -f ./$(DEPDIR)/eh8300self.Po
++ -rm -f ./$(DEPDIR)/eh8300self_linux.Po
++ -rm -f ./$(DEPDIR)/eh8300snelf.Po
++ -rm -f ./$(DEPDIR)/eh8300sxelf.Po
++ -rm -f ./$(DEPDIR)/eh8300sxelf_linux.Po
++ -rm -f ./$(DEPDIR)/eh8300sxnelf.Po
++ -rm -f ./$(DEPDIR)/ehppa64linux.Po
++ -rm -f ./$(DEPDIR)/ehppaelf.Po
++ -rm -f ./$(DEPDIR)/ehppalinux.Po
++ -rm -f ./$(DEPDIR)/ehppanbsd.Po
++ -rm -f ./$(DEPDIR)/ehppaobsd.Po
++ -rm -f ./$(DEPDIR)/ei386aout.Po
++ -rm -f ./$(DEPDIR)/ei386beos.Po
++ -rm -f ./$(DEPDIR)/ei386bsd.Po
++ -rm -f ./$(DEPDIR)/ei386go32.Po
++ -rm -f ./$(DEPDIR)/ei386lynx.Po
++ -rm -f ./$(DEPDIR)/ei386moss.Po
++ -rm -f ./$(DEPDIR)/ei386msdos.Po
++ -rm -f ./$(DEPDIR)/ei386nto.Po
++ -rm -f ./$(DEPDIR)/ei386pe.Po
++ -rm -f ./$(DEPDIR)/ei386pe_posix.Po
++ -rm -f ./$(DEPDIR)/ei386pep.Po
++ -rm -f ./$(DEPDIR)/em32relf.Po
++ -rm -f ./$(DEPDIR)/em32relf_linux.Po
++ -rm -f ./$(DEPDIR)/em32rlelf.Po
++ -rm -f ./$(DEPDIR)/em32rlelf_linux.Po
++ -rm -f ./$(DEPDIR)/em68hc11elf.Po
++ -rm -f ./$(DEPDIR)/em68hc11elfb.Po
++ -rm -f ./$(DEPDIR)/em68hc12elf.Po
++ -rm -f ./$(DEPDIR)/em68hc12elfb.Po
++ -rm -f ./$(DEPDIR)/em68kelf.Po
++ -rm -f ./$(DEPDIR)/em68kelfnbsd.Po
++ -rm -f ./$(DEPDIR)/em9s12zelf.Po
++ -rm -f ./$(DEPDIR)/emcorepe.Po
++ -rm -f ./$(DEPDIR)/emmo.Po
++ -rm -f ./$(DEPDIR)/emn10200.Po
++ -rm -f ./$(DEPDIR)/emn10300.Po
++ -rm -f ./$(DEPDIR)/emoxiebox.Po
++ -rm -f ./$(DEPDIR)/emsp430X.Po
++ -rm -f ./$(DEPDIR)/emsp430elf.Po
++ -rm -f ./$(DEPDIR)/ends32belf.Po
++ -rm -f ./$(DEPDIR)/ends32belf16m.Po
++ -rm -f ./$(DEPDIR)/ends32belf_linux.Po
++ -rm -f ./$(DEPDIR)/ends32elf.Po
++ -rm -f ./$(DEPDIR)/ends32elf16m.Po
++ -rm -f ./$(DEPDIR)/ends32elf_linux.Po
++ -rm -f ./$(DEPDIR)/enios2elf.Po
++ -rm -f ./$(DEPDIR)/enios2linux.Po
++ -rm -f ./$(DEPDIR)/ens32knbsd.Po
++ -rm -f ./$(DEPDIR)/epc532macha.Po
++ -rm -f ./$(DEPDIR)/epdp11.Po
++ -rm -f ./$(DEPDIR)/epjelf.Po
++ -rm -f ./$(DEPDIR)/epjlelf.Po
++ -rm -f ./$(DEPDIR)/eppcmacos.Po
++ -rm -f ./$(DEPDIR)/epruelf.Po
++ -rm -f ./$(DEPDIR)/escore3_elf.Po
++ -rm -f ./$(DEPDIR)/escore7_elf.Po
++ -rm -f ./$(DEPDIR)/esh.Po
++ -rm -f ./$(DEPDIR)/eshelf.Po
++ -rm -f ./$(DEPDIR)/eshelf_fd.Po
++ -rm -f ./$(DEPDIR)/eshelf_linux.Po
++ -rm -f ./$(DEPDIR)/eshelf_nbsd.Po
++ -rm -f ./$(DEPDIR)/eshelf_nto.Po
++ -rm -f ./$(DEPDIR)/eshelf_uclinux.Po
++ -rm -f ./$(DEPDIR)/eshelf_vxworks.Po
++ -rm -f ./$(DEPDIR)/eshl.Po
++ -rm -f ./$(DEPDIR)/eshlelf.Po
++ -rm -f ./$(DEPDIR)/eshlelf_fd.Po
++ -rm -f ./$(DEPDIR)/eshlelf_linux.Po
++ -rm -f ./$(DEPDIR)/eshlelf_nbsd.Po
++ -rm -f ./$(DEPDIR)/eshlelf_nto.Po
++ -rm -f ./$(DEPDIR)/eshlelf_vxworks.Po
++ -rm -f ./$(DEPDIR)/eshpe.Po
++ -rm -f ./$(DEPDIR)/etic30coff.Po
++ -rm -f ./$(DEPDIR)/etic3xcoff.Po
++ -rm -f ./$(DEPDIR)/etic3xcoff_onchip.Po
++ -rm -f ./$(DEPDIR)/etic4xcoff.Po
++ -rm -f ./$(DEPDIR)/etic54xcoff.Po
++ -rm -f ./$(DEPDIR)/ev850.Po
++ -rm -f ./$(DEPDIR)/ev850_rh850.Po
++ -rm -f ./$(DEPDIR)/evanilla.Po
++ -rm -f ./$(DEPDIR)/evaxnbsd.Po
++ -rm -f ./$(DEPDIR)/exgateelf.Po
++ -rm -f ./$(DEPDIR)/ez80.Po
++ -rm -f ./$(DEPDIR)/ez8001.Po
++ -rm -f ./$(DEPDIR)/ez8002.Po
++ -rm -f ./$(DEPDIR)/ldbuildid.Po
++ -rm -f ./$(DEPDIR)/ldcref.Po
++ -rm -f ./$(DEPDIR)/ldctor.Po
++ -rm -f ./$(DEPDIR)/ldelf.Po
++ -rm -f ./$(DEPDIR)/ldelfgen.Po
++ -rm -f ./$(DEPDIR)/ldemul.Po
++ -rm -f ./$(DEPDIR)/ldexp.Po
++ -rm -f ./$(DEPDIR)/ldfile.Po
++ -rm -f ./$(DEPDIR)/ldgram.Po
++ -rm -f ./$(DEPDIR)/ldlang.Po
++ -rm -f ./$(DEPDIR)/ldlex-wrapper.Po
++ -rm -f ./$(DEPDIR)/ldlex.Po
++ -rm -f ./$(DEPDIR)/ldmain.Po
++ -rm -f ./$(DEPDIR)/ldmisc.Po
++ -rm -f ./$(DEPDIR)/ldver.Po
++ -rm -f ./$(DEPDIR)/ldwrite.Po
++ -rm -f ./$(DEPDIR)/lexsup.Po
++ -rm -f ./$(DEPDIR)/libdep_plugin.Plo
++ -rm -f ./$(DEPDIR)/libldtestplug2_la-testplug2.Plo
++ -rm -f ./$(DEPDIR)/libldtestplug3_la-testplug3.Plo
++ -rm -f ./$(DEPDIR)/libldtestplug4_la-testplug4.Plo
++ -rm -f ./$(DEPDIR)/libldtestplug_la-testplug.Plo
++ -rm -f ./$(DEPDIR)/mri.Po
++ -rm -f ./$(DEPDIR)/pdb.Po
++ -rm -f ./$(DEPDIR)/pe-dll.Po
++ -rm -f ./$(DEPDIR)/pep-dll.Po
++ -rm -f ./$(DEPDIR)/plugin.Po
+ -rm -f Makefile
+ distclean-am: clean-am distclean-DEJAGNU distclean-compile \
+ distclean-generic distclean-hdr distclean-libtool \
+@@ -2163,7 +2659,340 @@ installcheck-am:
+ maintainer-clean: maintainer-clean-recursive
+ -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+ -rm -rf $(top_srcdir)/autom4te.cache
+- -rm -rf ./$(DEPDIR)
++ -rm -f ./$(DEPDIR)/deffilep.Po
++ -rm -f ./$(DEPDIR)/eaarch64cloudabi.Po
++ -rm -f ./$(DEPDIR)/eaarch64cloudabib.Po
++ -rm -f ./$(DEPDIR)/eaarch64elf.Po
++ -rm -f ./$(DEPDIR)/eaarch64elf32.Po
++ -rm -f ./$(DEPDIR)/eaarch64elf32b.Po
++ -rm -f ./$(DEPDIR)/eaarch64elfb.Po
++ -rm -f ./$(DEPDIR)/eaarch64fbsd.Po
++ -rm -f ./$(DEPDIR)/eaarch64fbsdb.Po
++ -rm -f ./$(DEPDIR)/eaarch64haiku.Po
++ -rm -f ./$(DEPDIR)/eaarch64linux.Po
++ -rm -f ./$(DEPDIR)/eaarch64linux32.Po
++ -rm -f ./$(DEPDIR)/eaarch64linux32b.Po
++ -rm -f ./$(DEPDIR)/eaarch64linuxb.Po
++ -rm -f ./$(DEPDIR)/eaarch64pe.Po
++ -rm -f ./$(DEPDIR)/eaix5ppc.Po
++ -rm -f ./$(DEPDIR)/eaix5rs6.Po
++ -rm -f ./$(DEPDIR)/eaixppc.Po
++ -rm -f ./$(DEPDIR)/eaixrs6.Po
++ -rm -f ./$(DEPDIR)/ealpha.Po
++ -rm -f ./$(DEPDIR)/ealphavms.Po
++ -rm -f ./$(DEPDIR)/earcelf.Po
++ -rm -f ./$(DEPDIR)/earclinux.Po
++ -rm -f ./$(DEPDIR)/earclinux_nps.Po
++ -rm -f ./$(DEPDIR)/earcv2elf.Po
++ -rm -f ./$(DEPDIR)/earcv2elfx.Po
++ -rm -f ./$(DEPDIR)/earm_wince_pe.Po
++ -rm -f ./$(DEPDIR)/earmelf.Po
++ -rm -f ./$(DEPDIR)/earmelf_fbsd.Po
++ -rm -f ./$(DEPDIR)/earmelf_fuchsia.Po
++ -rm -f ./$(DEPDIR)/earmelf_haiku.Po
++ -rm -f ./$(DEPDIR)/earmelf_linux.Po
++ -rm -f ./$(DEPDIR)/earmelf_linux_eabi.Po
++ -rm -f ./$(DEPDIR)/earmelf_linux_fdpiceabi.Po
++ -rm -f ./$(DEPDIR)/earmelf_nacl.Po
++ -rm -f ./$(DEPDIR)/earmelf_nbsd.Po
++ -rm -f ./$(DEPDIR)/earmelf_phoenix.Po
++ -rm -f ./$(DEPDIR)/earmelf_vxworks.Po
++ -rm -f ./$(DEPDIR)/earmelfb.Po
++ -rm -f ./$(DEPDIR)/earmelfb_fbsd.Po
++ -rm -f ./$(DEPDIR)/earmelfb_fuchsia.Po
++ -rm -f ./$(DEPDIR)/earmelfb_linux.Po
++ -rm -f ./$(DEPDIR)/earmelfb_linux_eabi.Po
++ -rm -f ./$(DEPDIR)/earmelfb_linux_fdpiceabi.Po
++ -rm -f ./$(DEPDIR)/earmelfb_nacl.Po
++ -rm -f ./$(DEPDIR)/earmelfb_nbsd.Po
++ -rm -f ./$(DEPDIR)/earmnto.Po
++ -rm -f ./$(DEPDIR)/earmpe.Po
++ -rm -f ./$(DEPDIR)/eavr1.Po
++ -rm -f ./$(DEPDIR)/eavr2.Po
++ -rm -f ./$(DEPDIR)/eavr25.Po
++ -rm -f ./$(DEPDIR)/eavr3.Po
++ -rm -f ./$(DEPDIR)/eavr31.Po
++ -rm -f ./$(DEPDIR)/eavr35.Po
++ -rm -f ./$(DEPDIR)/eavr4.Po
++ -rm -f ./$(DEPDIR)/eavr5.Po
++ -rm -f ./$(DEPDIR)/eavr51.Po
++ -rm -f ./$(DEPDIR)/eavr6.Po
++ -rm -f ./$(DEPDIR)/eavrtiny.Po
++ -rm -f ./$(DEPDIR)/eavrxmega1.Po
++ -rm -f ./$(DEPDIR)/eavrxmega2.Po
++ -rm -f ./$(DEPDIR)/eavrxmega3.Po
++ -rm -f ./$(DEPDIR)/eavrxmega4.Po
++ -rm -f ./$(DEPDIR)/eavrxmega5.Po
++ -rm -f ./$(DEPDIR)/eavrxmega6.Po
++ -rm -f ./$(DEPDIR)/eavrxmega7.Po
++ -rm -f ./$(DEPDIR)/ecrisaout.Po
++ -rm -f ./$(DEPDIR)/ecriself.Po
++ -rm -f ./$(DEPDIR)/ecrislinux.Po
++ -rm -f ./$(DEPDIR)/ecskyelf.Po
++ -rm -f ./$(DEPDIR)/ecskyelf_linux.Po
++ -rm -f ./$(DEPDIR)/ed10velf.Po
++ -rm -f ./$(DEPDIR)/ed30v_e.Po
++ -rm -f ./$(DEPDIR)/ed30v_o.Po
++ -rm -f ./$(DEPDIR)/ed30velf.Po
++ -rm -f ./$(DEPDIR)/eelf32_dlx.Po
++ -rm -f ./$(DEPDIR)/eelf32_sparc.Po
++ -rm -f ./$(DEPDIR)/eelf32_sparc_sol2.Po
++ -rm -f ./$(DEPDIR)/eelf32_sparc_vxworks.Po
++ -rm -f ./$(DEPDIR)/eelf32_spu.Po
++ -rm -f ./$(DEPDIR)/eelf32_tic6x_be.Po
++ -rm -f ./$(DEPDIR)/eelf32_tic6x_elf_be.Po
++ -rm -f ./$(DEPDIR)/eelf32_tic6x_elf_le.Po
++ -rm -f ./$(DEPDIR)/eelf32_tic6x_le.Po
++ -rm -f ./$(DEPDIR)/eelf32_tic6x_linux_be.Po
++ -rm -f ./$(DEPDIR)/eelf32_tic6x_linux_le.Po
++ -rm -f ./$(DEPDIR)/eelf32_x86_64.Po
++ -rm -f ./$(DEPDIR)/eelf32am33lin.Po
++ -rm -f ./$(DEPDIR)/eelf32b4300.Po
++ -rm -f ./$(DEPDIR)/eelf32bfin.Po
++ -rm -f ./$(DEPDIR)/eelf32bfinfd.Po
++ -rm -f ./$(DEPDIR)/eelf32bmip.Po
++ -rm -f ./$(DEPDIR)/eelf32bmipn32.Po
++ -rm -f ./$(DEPDIR)/eelf32briscv.Po
++ -rm -f ./$(DEPDIR)/eelf32briscv_ilp32.Po
++ -rm -f ./$(DEPDIR)/eelf32briscv_ilp32f.Po
++ -rm -f ./$(DEPDIR)/eelf32bsmip.Po
++ -rm -f ./$(DEPDIR)/eelf32btsmip.Po
++ -rm -f ./$(DEPDIR)/eelf32btsmip_fbsd.Po
++ -rm -f ./$(DEPDIR)/eelf32btsmipn32.Po
++ -rm -f ./$(DEPDIR)/eelf32btsmipn32_fbsd.Po
++ -rm -f ./$(DEPDIR)/eelf32cr16.Po
++ -rm -f ./$(DEPDIR)/eelf32crx.Po
++ -rm -f ./$(DEPDIR)/eelf32ebmip.Po
++ -rm -f ./$(DEPDIR)/eelf32ebmipvxworks.Po
++ -rm -f ./$(DEPDIR)/eelf32elmip.Po
++ -rm -f ./$(DEPDIR)/eelf32elmipvxworks.Po
++ -rm -f ./$(DEPDIR)/eelf32epiphany.Po
++ -rm -f ./$(DEPDIR)/eelf32epiphany_4x4.Po
++ -rm -f ./$(DEPDIR)/eelf32fr30.Po
++ -rm -f ./$(DEPDIR)/eelf32frv.Po
++ -rm -f ./$(DEPDIR)/eelf32frvfd.Po
++ -rm -f ./$(DEPDIR)/eelf32ft32.Po
++ -rm -f ./$(DEPDIR)/eelf32ip2k.Po
++ -rm -f ./$(DEPDIR)/eelf32iq10.Po
++ -rm -f ./$(DEPDIR)/eelf32iq2000.Po
++ -rm -f ./$(DEPDIR)/eelf32l4300.Po
++ -rm -f ./$(DEPDIR)/eelf32lm32.Po
++ -rm -f ./$(DEPDIR)/eelf32lm32fd.Po
++ -rm -f ./$(DEPDIR)/eelf32lmip.Po
++ -rm -f ./$(DEPDIR)/eelf32loongarch.Po
++ -rm -f ./$(DEPDIR)/eelf32lppc.Po
++ -rm -f ./$(DEPDIR)/eelf32lppclinux.Po
++ -rm -f ./$(DEPDIR)/eelf32lppcnto.Po
++ -rm -f ./$(DEPDIR)/eelf32lppcsim.Po
++ -rm -f ./$(DEPDIR)/eelf32lr5900.Po
++ -rm -f ./$(DEPDIR)/eelf32lr5900n32.Po
++ -rm -f ./$(DEPDIR)/eelf32lriscv.Po
++ -rm -f ./$(DEPDIR)/eelf32lriscv_ilp32.Po
++ -rm -f ./$(DEPDIR)/eelf32lriscv_ilp32f.Po
++ -rm -f ./$(DEPDIR)/eelf32lsmip.Po
++ -rm -f ./$(DEPDIR)/eelf32ltsmip.Po
++ -rm -f ./$(DEPDIR)/eelf32ltsmip_fbsd.Po
++ -rm -f ./$(DEPDIR)/eelf32ltsmipn32.Po
++ -rm -f ./$(DEPDIR)/eelf32ltsmipn32_fbsd.Po
++ -rm -f ./$(DEPDIR)/eelf32m32c.Po
++ -rm -f ./$(DEPDIR)/eelf32mb_linux.Po
++ -rm -f ./$(DEPDIR)/eelf32mbel_linux.Po
++ -rm -f ./$(DEPDIR)/eelf32mcore.Po
++ -rm -f ./$(DEPDIR)/eelf32mep.Po
++ -rm -f ./$(DEPDIR)/eelf32metag.Po
++ -rm -f ./$(DEPDIR)/eelf32microblaze.Po
++ -rm -f ./$(DEPDIR)/eelf32microblazeel.Po
++ -rm -f ./$(DEPDIR)/eelf32mipswindiss.Po
++ -rm -f ./$(DEPDIR)/eelf32moxie.Po
++ -rm -f ./$(DEPDIR)/eelf32mt.Po
++ -rm -f ./$(DEPDIR)/eelf32or1k.Po
++ -rm -f ./$(DEPDIR)/eelf32or1k_linux.Po
++ -rm -f ./$(DEPDIR)/eelf32ppc.Po
++ -rm -f ./$(DEPDIR)/eelf32ppc_fbsd.Po
++ -rm -f ./$(DEPDIR)/eelf32ppchaiku.Po
++ -rm -f ./$(DEPDIR)/eelf32ppclinux.Po
++ -rm -f ./$(DEPDIR)/eelf32ppcnto.Po
++ -rm -f ./$(DEPDIR)/eelf32ppcsim.Po
++ -rm -f ./$(DEPDIR)/eelf32ppcvxworks.Po
++ -rm -f ./$(DEPDIR)/eelf32ppcwindiss.Po
++ -rm -f ./$(DEPDIR)/eelf32rl78.Po
++ -rm -f ./$(DEPDIR)/eelf32rx.Po
++ -rm -f ./$(DEPDIR)/eelf32rx_linux.Po
++ -rm -f ./$(DEPDIR)/eelf32tilegx.Po
++ -rm -f ./$(DEPDIR)/eelf32tilegx_be.Po
++ -rm -f ./$(DEPDIR)/eelf32tilepro.Po
++ -rm -f ./$(DEPDIR)/eelf32vax.Po
++ -rm -f ./$(DEPDIR)/eelf32visium.Po
++ -rm -f ./$(DEPDIR)/eelf32xstormy16.Po
++ -rm -f ./$(DEPDIR)/eelf32xtensa.Po
++ -rm -f ./$(DEPDIR)/eelf32z80.Po
++ -rm -f ./$(DEPDIR)/eelf64_aix.Po
++ -rm -f ./$(DEPDIR)/eelf64_ia64.Po
++ -rm -f ./$(DEPDIR)/eelf64_ia64_fbsd.Po
++ -rm -f ./$(DEPDIR)/eelf64_ia64_vms.Po
++ -rm -f ./$(DEPDIR)/eelf64_s390.Po
++ -rm -f ./$(DEPDIR)/eelf64_sparc.Po
++ -rm -f ./$(DEPDIR)/eelf64_sparc_fbsd.Po
++ -rm -f ./$(DEPDIR)/eelf64_sparc_sol2.Po
++ -rm -f ./$(DEPDIR)/eelf64alpha.Po
++ -rm -f ./$(DEPDIR)/eelf64alpha_fbsd.Po
++ -rm -f ./$(DEPDIR)/eelf64alpha_nbsd.Po
++ -rm -f ./$(DEPDIR)/eelf64bmip.Po
++ -rm -f ./$(DEPDIR)/eelf64bpf.Po
++ -rm -f ./$(DEPDIR)/eelf64briscv.Po
++ -rm -f ./$(DEPDIR)/eelf64briscv_lp64.Po
++ -rm -f ./$(DEPDIR)/eelf64briscv_lp64f.Po
++ -rm -f ./$(DEPDIR)/eelf64btsmip.Po
++ -rm -f ./$(DEPDIR)/eelf64btsmip_fbsd.Po
++ -rm -f ./$(DEPDIR)/eelf64hppa.Po
++ -rm -f ./$(DEPDIR)/eelf64loongarch.Po
++ -rm -f ./$(DEPDIR)/eelf64lppc.Po
++ -rm -f ./$(DEPDIR)/eelf64lppc_fbsd.Po
++ -rm -f ./$(DEPDIR)/eelf64lriscv.Po
++ -rm -f ./$(DEPDIR)/eelf64lriscv_lp64.Po
++ -rm -f ./$(DEPDIR)/eelf64lriscv_lp64f.Po
++ -rm -f ./$(DEPDIR)/eelf64ltsmip.Po
++ -rm -f ./$(DEPDIR)/eelf64ltsmip_fbsd.Po
++ -rm -f ./$(DEPDIR)/eelf64mmix.Po
++ -rm -f ./$(DEPDIR)/eelf64ppc.Po
++ -rm -f ./$(DEPDIR)/eelf64ppc_fbsd.Po
++ -rm -f ./$(DEPDIR)/eelf64rdos.Po
++ -rm -f ./$(DEPDIR)/eelf64tilegx.Po
++ -rm -f ./$(DEPDIR)/eelf64tilegx_be.Po
++ -rm -f ./$(DEPDIR)/eelf_i386.Po
++ -rm -f ./$(DEPDIR)/eelf_i386_be.Po
++ -rm -f ./$(DEPDIR)/eelf_i386_fbsd.Po
++ -rm -f ./$(DEPDIR)/eelf_i386_haiku.Po
++ -rm -f ./$(DEPDIR)/eelf_i386_ldso.Po
++ -rm -f ./$(DEPDIR)/eelf_i386_sb.Po
++ -rm -f ./$(DEPDIR)/eelf_i386_sol2.Po
++ -rm -f ./$(DEPDIR)/eelf_i386_vxworks.Po
++ -rm -f ./$(DEPDIR)/eelf_iamcu.Po
++ -rm -f ./$(DEPDIR)/eelf_mipsel_haiku.Po
++ -rm -f ./$(DEPDIR)/eelf_s390.Po
++ -rm -f ./$(DEPDIR)/eelf_x86_64.Po
++ -rm -f ./$(DEPDIR)/eelf_x86_64_cloudabi.Po
++ -rm -f ./$(DEPDIR)/eelf_x86_64_fbsd.Po
++ -rm -f ./$(DEPDIR)/eelf_x86_64_haiku.Po
++ -rm -f ./$(DEPDIR)/eelf_x86_64_sol2.Po
++ -rm -f ./$(DEPDIR)/eh8300elf.Po
++ -rm -f ./$(DEPDIR)/eh8300elf_linux.Po
++ -rm -f ./$(DEPDIR)/eh8300helf.Po
++ -rm -f ./$(DEPDIR)/eh8300helf_linux.Po
++ -rm -f ./$(DEPDIR)/eh8300hnelf.Po
++ -rm -f ./$(DEPDIR)/eh8300self.Po
++ -rm -f ./$(DEPDIR)/eh8300self_linux.Po
++ -rm -f ./$(DEPDIR)/eh8300snelf.Po
++ -rm -f ./$(DEPDIR)/eh8300sxelf.Po
++ -rm -f ./$(DEPDIR)/eh8300sxelf_linux.Po
++ -rm -f ./$(DEPDIR)/eh8300sxnelf.Po
++ -rm -f ./$(DEPDIR)/ehppa64linux.Po
++ -rm -f ./$(DEPDIR)/ehppaelf.Po
++ -rm -f ./$(DEPDIR)/ehppalinux.Po
++ -rm -f ./$(DEPDIR)/ehppanbsd.Po
++ -rm -f ./$(DEPDIR)/ehppaobsd.Po
++ -rm -f ./$(DEPDIR)/ei386aout.Po
++ -rm -f ./$(DEPDIR)/ei386beos.Po
++ -rm -f ./$(DEPDIR)/ei386bsd.Po
++ -rm -f ./$(DEPDIR)/ei386go32.Po
++ -rm -f ./$(DEPDIR)/ei386lynx.Po
++ -rm -f ./$(DEPDIR)/ei386moss.Po
++ -rm -f ./$(DEPDIR)/ei386msdos.Po
++ -rm -f ./$(DEPDIR)/ei386nto.Po
++ -rm -f ./$(DEPDIR)/ei386pe.Po
++ -rm -f ./$(DEPDIR)/ei386pe_posix.Po
++ -rm -f ./$(DEPDIR)/ei386pep.Po
++ -rm -f ./$(DEPDIR)/em32relf.Po
++ -rm -f ./$(DEPDIR)/em32relf_linux.Po
++ -rm -f ./$(DEPDIR)/em32rlelf.Po
++ -rm -f ./$(DEPDIR)/em32rlelf_linux.Po
++ -rm -f ./$(DEPDIR)/em68hc11elf.Po
++ -rm -f ./$(DEPDIR)/em68hc11elfb.Po
++ -rm -f ./$(DEPDIR)/em68hc12elf.Po
++ -rm -f ./$(DEPDIR)/em68hc12elfb.Po
++ -rm -f ./$(DEPDIR)/em68kelf.Po
++ -rm -f ./$(DEPDIR)/em68kelfnbsd.Po
++ -rm -f ./$(DEPDIR)/em9s12zelf.Po
++ -rm -f ./$(DEPDIR)/emcorepe.Po
++ -rm -f ./$(DEPDIR)/emmo.Po
++ -rm -f ./$(DEPDIR)/emn10200.Po
++ -rm -f ./$(DEPDIR)/emn10300.Po
++ -rm -f ./$(DEPDIR)/emoxiebox.Po
++ -rm -f ./$(DEPDIR)/emsp430X.Po
++ -rm -f ./$(DEPDIR)/emsp430elf.Po
++ -rm -f ./$(DEPDIR)/ends32belf.Po
++ -rm -f ./$(DEPDIR)/ends32belf16m.Po
++ -rm -f ./$(DEPDIR)/ends32belf_linux.Po
++ -rm -f ./$(DEPDIR)/ends32elf.Po
++ -rm -f ./$(DEPDIR)/ends32elf16m.Po
++ -rm -f ./$(DEPDIR)/ends32elf_linux.Po
++ -rm -f ./$(DEPDIR)/enios2elf.Po
++ -rm -f ./$(DEPDIR)/enios2linux.Po
++ -rm -f ./$(DEPDIR)/ens32knbsd.Po
++ -rm -f ./$(DEPDIR)/epc532macha.Po
++ -rm -f ./$(DEPDIR)/epdp11.Po
++ -rm -f ./$(DEPDIR)/epjelf.Po
++ -rm -f ./$(DEPDIR)/epjlelf.Po
++ -rm -f ./$(DEPDIR)/eppcmacos.Po
++ -rm -f ./$(DEPDIR)/epruelf.Po
++ -rm -f ./$(DEPDIR)/escore3_elf.Po
++ -rm -f ./$(DEPDIR)/escore7_elf.Po
++ -rm -f ./$(DEPDIR)/esh.Po
++ -rm -f ./$(DEPDIR)/eshelf.Po
++ -rm -f ./$(DEPDIR)/eshelf_fd.Po
++ -rm -f ./$(DEPDIR)/eshelf_linux.Po
++ -rm -f ./$(DEPDIR)/eshelf_nbsd.Po
++ -rm -f ./$(DEPDIR)/eshelf_nto.Po
++ -rm -f ./$(DEPDIR)/eshelf_uclinux.Po
++ -rm -f ./$(DEPDIR)/eshelf_vxworks.Po
++ -rm -f ./$(DEPDIR)/eshl.Po
++ -rm -f ./$(DEPDIR)/eshlelf.Po
++ -rm -f ./$(DEPDIR)/eshlelf_fd.Po
++ -rm -f ./$(DEPDIR)/eshlelf_linux.Po
++ -rm -f ./$(DEPDIR)/eshlelf_nbsd.Po
++ -rm -f ./$(DEPDIR)/eshlelf_nto.Po
++ -rm -f ./$(DEPDIR)/eshlelf_vxworks.Po
++ -rm -f ./$(DEPDIR)/eshpe.Po
++ -rm -f ./$(DEPDIR)/etic30coff.Po
++ -rm -f ./$(DEPDIR)/etic3xcoff.Po
++ -rm -f ./$(DEPDIR)/etic3xcoff_onchip.Po
++ -rm -f ./$(DEPDIR)/etic4xcoff.Po
++ -rm -f ./$(DEPDIR)/etic54xcoff.Po
++ -rm -f ./$(DEPDIR)/ev850.Po
++ -rm -f ./$(DEPDIR)/ev850_rh850.Po
++ -rm -f ./$(DEPDIR)/evanilla.Po
++ -rm -f ./$(DEPDIR)/evaxnbsd.Po
++ -rm -f ./$(DEPDIR)/exgateelf.Po
++ -rm -f ./$(DEPDIR)/ez80.Po
++ -rm -f ./$(DEPDIR)/ez8001.Po
++ -rm -f ./$(DEPDIR)/ez8002.Po
++ -rm -f ./$(DEPDIR)/ldbuildid.Po
++ -rm -f ./$(DEPDIR)/ldcref.Po
++ -rm -f ./$(DEPDIR)/ldctor.Po
++ -rm -f ./$(DEPDIR)/ldelf.Po
++ -rm -f ./$(DEPDIR)/ldelfgen.Po
++ -rm -f ./$(DEPDIR)/ldemul.Po
++ -rm -f ./$(DEPDIR)/ldexp.Po
++ -rm -f ./$(DEPDIR)/ldfile.Po
++ -rm -f ./$(DEPDIR)/ldgram.Po
++ -rm -f ./$(DEPDIR)/ldlang.Po
++ -rm -f ./$(DEPDIR)/ldlex-wrapper.Po
++ -rm -f ./$(DEPDIR)/ldlex.Po
++ -rm -f ./$(DEPDIR)/ldmain.Po
++ -rm -f ./$(DEPDIR)/ldmisc.Po
++ -rm -f ./$(DEPDIR)/ldver.Po
++ -rm -f ./$(DEPDIR)/ldwrite.Po
++ -rm -f ./$(DEPDIR)/lexsup.Po
++ -rm -f ./$(DEPDIR)/libdep_plugin.Plo
++ -rm -f ./$(DEPDIR)/libldtestplug2_la-testplug2.Plo
++ -rm -f ./$(DEPDIR)/libldtestplug3_la-testplug3.Plo
++ -rm -f ./$(DEPDIR)/libldtestplug4_la-testplug4.Plo
++ -rm -f ./$(DEPDIR)/libldtestplug_la-testplug.Plo
++ -rm -f ./$(DEPDIR)/mri.Po
++ -rm -f ./$(DEPDIR)/pdb.Po
++ -rm -f ./$(DEPDIR)/pe-dll.Po
++ -rm -f ./$(DEPDIR)/pep-dll.Po
++ -rm -f ./$(DEPDIR)/plugin.Po
+ -rm -f Makefile
+ maintainer-clean-am: distclean-am maintainer-clean-aminfo \
+ maintainer-clean-generic
+@@ -2188,21 +3017,22 @@ uninstall-am: uninstall-bfdpluginLTLIBRARIES uninstall-binPROGRAMS \
+ uninstall-man: uninstall-man1
+
+ .MAKE: $(am__recursive_targets) all check check-am install install-am \
+- install-strip
++ install-exec install-strip
+
+ .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \
+- am--refresh check check-DEJAGNU check-am clean clean-aminfo \
+- clean-bfdpluginLTLIBRARIES clean-binPROGRAMS clean-cscope \
+- clean-generic clean-libtool clean-noinstLTLIBRARIES cscope \
+- cscopelist-am ctags ctags-am dist-info distclean \
+- distclean-DEJAGNU distclean-compile distclean-generic \
+- distclean-hdr distclean-libtool distclean-local distclean-tags \
+- dvi dvi-am html html-am html-local info info-am install \
+- install-am install-bfdpluginLTLIBRARIES install-binPROGRAMS \
+- install-data install-data-am install-data-local install-dvi \
+- install-dvi-am install-exec install-exec-am install-exec-local \
+- install-html install-html-am install-info install-info-am \
+- install-man install-man1 install-pdf install-pdf-am install-ps \
++ am--depfiles am--refresh check check-DEJAGNU check-am clean \
++ clean-aminfo clean-bfdpluginLTLIBRARIES clean-binPROGRAMS \
++ clean-cscope clean-generic clean-libtool \
++ clean-noinstLTLIBRARIES cscope cscopelist-am ctags ctags-am \
++ dist-info distclean distclean-DEJAGNU distclean-compile \
++ distclean-generic distclean-hdr distclean-libtool \
++ distclean-local distclean-tags dvi dvi-am html html-am \
++ html-local info info-am install install-am \
++ install-bfdpluginLTLIBRARIES install-binPROGRAMS install-data \
++ install-data-am install-data-local install-dvi install-dvi-am \
++ install-exec install-exec-am install-exec-local install-html \
++ install-html-am install-info install-info-am install-man \
++ install-man1 install-pdf install-pdf-am install-ps \
+ install-ps-am install-strip installcheck installcheck-am \
+ installdirs installdirs-am maintainer-clean \
+ maintainer-clean-aminfo maintainer-clean-generic mostlyclean \
+@@ -2444,6 +3274,8 @@ $(ALL_EMULATION_SOURCES) $(ALL_64_EMULATION_SOURCES): $(GEN_DEPENDS)
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32xtensa.Pc@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32z80.Pc@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_i386.Pc@am__quote@
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_i386_sb.Pc@am__quote@
++#@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_x86_64_sb.Pc@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_i386_be.Pc@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_i386_fbsd.Pc@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_i386_haiku.Pc@am__quote@
+diff --git a/ld/aclocal.m4 b/ld/aclocal.m4
+index 893e973e..1cd19c59 100644
+--- a/ld/aclocal.m4
++++ b/ld/aclocal.m4
+@@ -1,6 +1,6 @@
+-# generated automatically by aclocal 1.15.1 -*- Autoconf -*-
++# generated automatically by aclocal 1.16.5 -*- Autoconf -*-
+
+-# Copyright (C) 1996-2017 Free Software Foundation, Inc.
++# Copyright (C) 1996-2021 Free Software Foundation, Inc.
+
+ # This file is free software; the Free Software Foundation
+ # gives unlimited permission to copy and/or distribute it,
+@@ -20,7 +20,9991 @@ You have another version of autoconf. It may work, but is not guaranteed to.
+ If you have problems, you may need to regenerate the build system entirely.
+ To do so, use the procedure documented by the package, typically 'autoreconf'.])])
+
+-# Copyright (C) 2002-2017 Free Software Foundation, Inc.
++# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*-
++#
++# Copyright (C) 1996-2001, 2003-2019, 2021-2022 Free Software
++# Foundation, Inc.
++# Written by Gordon Matzigkeit, 1996
++#
++# This file is free software; the Free Software Foundation gives
++# unlimited permission to copy and/or distribute it, with or without
++# modifications, as long as this notice is preserved.
++
++m4_define([_LT_COPYING], [dnl
++# Copyright (C) 2014 Free Software Foundation, Inc.
++# This is free software; see the source for copying conditions. There is NO
++# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
++
++# GNU Libtool 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 2 of of the License, or
++# (at your option) any later version.
++#
++# As a special exception to the GNU General Public License, if you
++# distribute this file as part of a program or library that is built
++# using GNU Libtool, you may include this file under the same
++# distribution terms that you use for the rest of that program.
++#
++# GNU Libtool 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 this program. If not, see <http://www.gnu.org/licenses/>.
++])
++
++# serial 59 LT_INIT
++
++
++# LT_PREREQ(VERSION)
++# ------------------
++# Complain and exit if this libtool version is less that VERSION.
++m4_defun([LT_PREREQ],
++[m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1,
++ [m4_default([$3],
++ [m4_fatal([Libtool version $1 or higher is required],
++ 63)])],
++ [$2])])
++
++
++# _LT_CHECK_BUILDDIR
++# ------------------
++# Complain if the absolute build directory name contains unusual characters
++m4_defun([_LT_CHECK_BUILDDIR],
++[case `pwd` in
++ *\ * | *\ *)
++ AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;;
++esac
++])
++
++
++# LT_INIT([OPTIONS])
++# ------------------
++AC_DEFUN([LT_INIT],
++[AC_PREREQ([2.62])dnl We use AC_PATH_PROGS_FEATURE_CHECK
++AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl
++AC_BEFORE([$0], [LT_LANG])dnl
++AC_BEFORE([$0], [LT_OUTPUT])dnl
++AC_BEFORE([$0], [LTDL_INIT])dnl
++m4_require([_LT_CHECK_BUILDDIR])dnl
++
++dnl Autoconf doesn't catch unexpanded LT_ macros by default:
++m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl
++m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl
++dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4
++dnl unless we require an AC_DEFUNed macro:
++AC_REQUIRE([LTOPTIONS_VERSION])dnl
++AC_REQUIRE([LTSUGAR_VERSION])dnl
++AC_REQUIRE([LTVERSION_VERSION])dnl
++AC_REQUIRE([LTOBSOLETE_VERSION])dnl
++m4_require([_LT_PROG_LTMAIN])dnl
++
++_LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}])
++
++dnl Parse OPTIONS
++_LT_SET_OPTIONS([$0], [$1])
++
++# This can be used to rebuild libtool when needed
++LIBTOOL_DEPS=$ltmain
++
++# Always use our own libtool.
++LIBTOOL='$(SHELL) $(top_builddir)/libtool'
++AC_SUBST(LIBTOOL)dnl
++
++_LT_SETUP
++
++# Only expand once:
++m4_define([LT_INIT])
++])# LT_INIT
++
++# Old names:
++AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT])
++AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT])
++dnl aclocal-1.4 backwards compatibility:
++dnl AC_DEFUN([AC_PROG_LIBTOOL], [])
++dnl AC_DEFUN([AM_PROG_LIBTOOL], [])
++
++
++# _LT_PREPARE_CC_BASENAME
++# -----------------------
++m4_defun([_LT_PREPARE_CC_BASENAME], [
++# Calculate cc_basename. Skip known compiler wrappers and cross-prefix.
++func_cc_basename ()
++{
++ for cc_temp in @S|@*""; do
++ case $cc_temp in
++ compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;;
++ distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;;
++ \-*) ;;
++ *) break;;
++ esac
++ done
++ func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"`
++}
++])# _LT_PREPARE_CC_BASENAME
++
++
++# _LT_CC_BASENAME(CC)
++# -------------------
++# It would be clearer to call AC_REQUIREs from _LT_PREPARE_CC_BASENAME,
++# but that macro is also expanded into generated libtool script, which
++# arranges for $SED and $ECHO to be set by different means.
++m4_defun([_LT_CC_BASENAME],
++[m4_require([_LT_PREPARE_CC_BASENAME])dnl
++AC_REQUIRE([_LT_DECL_SED])dnl
++AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl
++func_cc_basename $1
++cc_basename=$func_cc_basename_result
++])
++
++
++# _LT_FILEUTILS_DEFAULTS
++# ----------------------
++# It is okay to use these file commands and assume they have been set
++# sensibly after 'm4_require([_LT_FILEUTILS_DEFAULTS])'.
++m4_defun([_LT_FILEUTILS_DEFAULTS],
++[: ${CP="cp -f"}
++: ${MV="mv -f"}
++: ${RM="rm -f"}
++])# _LT_FILEUTILS_DEFAULTS
++
++
++# _LT_SETUP
++# ---------
++m4_defun([_LT_SETUP],
++[AC_REQUIRE([AC_CANONICAL_HOST])dnl
++AC_REQUIRE([AC_CANONICAL_BUILD])dnl
++AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl
++AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl
++
++_LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl
++dnl
++_LT_DECL([], [host_alias], [0], [The host system])dnl
++_LT_DECL([], [host], [0])dnl
++_LT_DECL([], [host_os], [0])dnl
++dnl
++_LT_DECL([], [build_alias], [0], [The build system])dnl
++_LT_DECL([], [build], [0])dnl
++_LT_DECL([], [build_os], [0])dnl
++dnl
++AC_REQUIRE([AC_PROG_CC])dnl
++AC_REQUIRE([LT_PATH_LD])dnl
++AC_REQUIRE([LT_PATH_NM])dnl
++dnl
++AC_REQUIRE([AC_PROG_LN_S])dnl
++test -z "$LN_S" && LN_S="ln -s"
++_LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl
++dnl
++AC_REQUIRE([LT_CMD_MAX_LEN])dnl
++_LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl
++_LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl
++dnl
++m4_require([_LT_FILEUTILS_DEFAULTS])dnl
++m4_require([_LT_CHECK_SHELL_FEATURES])dnl
++m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl
++m4_require([_LT_CMD_RELOAD])dnl
++m4_require([_LT_DECL_FILECMD])dnl
++m4_require([_LT_CHECK_MAGIC_METHOD])dnl
++m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl
++m4_require([_LT_CMD_OLD_ARCHIVE])dnl
++m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl
++m4_require([_LT_WITH_SYSROOT])dnl
++m4_require([_LT_CMD_TRUNCATE])dnl
++
++_LT_CONFIG_LIBTOOL_INIT([
++# See if we are running on zsh, and set the options that allow our
++# commands through without removal of \ escapes INIT.
++if test -n "\${ZSH_VERSION+set}"; then
++ setopt NO_GLOB_SUBST
++fi
++])
++if test -n "${ZSH_VERSION+set}"; then
++ setopt NO_GLOB_SUBST
++fi
++
++_LT_CHECK_OBJDIR
++
++m4_require([_LT_TAG_COMPILER])dnl
++
++case $host_os in
++aix3*)
++ # AIX sometimes has problems with the GCC collect2 program. For some
++ # reason, if we set the COLLECT_NAMES environment variable, the problems
++ # vanish in a puff of smoke.
++ if test set != "${COLLECT_NAMES+set}"; then
++ COLLECT_NAMES=
++ export COLLECT_NAMES
++ fi
++ ;;
++esac
++
++# Global variables:
++ofile=libtool
++can_build_shared=yes
++
++# All known linkers require a '.a' archive for static linking (except MSVC and
++# ICC, which need '.lib').
++libext=a
++
++with_gnu_ld=$lt_cv_prog_gnu_ld
++
++old_CC=$CC
++old_CFLAGS=$CFLAGS
++
++# Set sane defaults for various variables
++test -z "$CC" && CC=cc
++test -z "$LTCC" && LTCC=$CC
++test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS
++test -z "$LD" && LD=ld
++test -z "$ac_objext" && ac_objext=o
++
++_LT_CC_BASENAME([$compiler])
++
++# Only perform the check for file, if the check method requires it
++test -z "$MAGIC_CMD" && MAGIC_CMD=file
++case $deplibs_check_method in
++file_magic*)
++ if test "$file_magic_cmd" = '$MAGIC_CMD'; then
++ _LT_PATH_MAGIC
++ fi
++ ;;
++esac
++
++# Use C for the default configuration in the libtool script
++LT_SUPPORTED_TAG([CC])
++_LT_LANG_C_CONFIG
++_LT_LANG_DEFAULT_CONFIG
++_LT_CONFIG_COMMANDS
++])# _LT_SETUP
++
++
++# _LT_PREPARE_SED_QUOTE_VARS
++# --------------------------
++# Define a few sed substitution that help us do robust quoting.
++m4_defun([_LT_PREPARE_SED_QUOTE_VARS],
++[# Backslashify metacharacters that are still active within
++# double-quoted strings.
++sed_quote_subst='s/\([["`$\\]]\)/\\\1/g'
++
++# Same as above, but do not quote variable references.
++double_quote_subst='s/\([["`\\]]\)/\\\1/g'
++
++# Sed substitution to delay expansion of an escaped shell variable in a
++# double_quote_subst'ed string.
++delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
++
++# Sed substitution to delay expansion of an escaped single quote.
++delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g'
++
++# Sed substitution to avoid accidental globbing in evaled expressions
++no_glob_subst='s/\*/\\\*/g'
++])
++
++# _LT_PROG_LTMAIN
++# ---------------
++# Note that this code is called both from 'configure', and 'config.status'
++# now that we use AC_CONFIG_COMMANDS to generate libtool. Notably,
++# 'config.status' has no value for ac_aux_dir unless we are using Automake,
++# so we pass a copy along to make sure it has a sensible value anyway.
++m4_defun([_LT_PROG_LTMAIN],
++[m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl
++_LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir'])
++ltmain=$ac_aux_dir/ltmain.sh
++])# _LT_PROG_LTMAIN
++
++
++
++# So that we can recreate a full libtool script including additional
++# tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS
++# in macros and then make a single call at the end using the 'libtool'
++# label.
++
++
++# _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS])
++# ----------------------------------------
++# Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later.
++m4_define([_LT_CONFIG_LIBTOOL_INIT],
++[m4_ifval([$1],
++ [m4_append([_LT_OUTPUT_LIBTOOL_INIT],
++ [$1
++])])])
++
++# Initialize.
++m4_define([_LT_OUTPUT_LIBTOOL_INIT])
++
++
++# _LT_CONFIG_LIBTOOL([COMMANDS])
++# ------------------------------
++# Register COMMANDS to be passed to AC_CONFIG_COMMANDS later.
++m4_define([_LT_CONFIG_LIBTOOL],
++[m4_ifval([$1],
++ [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS],
++ [$1
++])])])
++
++# Initialize.
++m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS])
++
++
++# _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS])
++# -----------------------------------------------------
++m4_defun([_LT_CONFIG_SAVE_COMMANDS],
++[_LT_CONFIG_LIBTOOL([$1])
++_LT_CONFIG_LIBTOOL_INIT([$2])
++])
++
++
++# _LT_FORMAT_COMMENT([COMMENT])
++# -----------------------------
++# Add leading comment marks to the start of each line, and a trailing
++# full-stop to the whole comment if one is not present already.
++m4_define([_LT_FORMAT_COMMENT],
++[m4_ifval([$1], [
++m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])],
++ [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.])
++)])
++
++
++
++
++
++# _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?])
++# -------------------------------------------------------------------
++# CONFIGNAME is the name given to the value in the libtool script.
++# VARNAME is the (base) name used in the configure script.
++# VALUE may be 0, 1 or 2 for a computed quote escaped value based on
++# VARNAME. Any other value will be used directly.
++m4_define([_LT_DECL],
++[lt_if_append_uniq([lt_decl_varnames], [$2], [, ],
++ [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name],
++ [m4_ifval([$1], [$1], [$2])])
++ lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3])
++ m4_ifval([$4],
++ [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])])
++ lt_dict_add_subkey([lt_decl_dict], [$2],
++ [tagged?], [m4_ifval([$5], [yes], [no])])])
++])
++
++
++# _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION])
++# --------------------------------------------------------
++m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])])
++
++
++# lt_decl_tag_varnames([SEPARATOR], [VARNAME1...])
++# ------------------------------------------------
++m4_define([lt_decl_tag_varnames],
++[_lt_decl_filter([tagged?], [yes], $@)])
++
++
++# _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..])
++# ---------------------------------------------------------
++m4_define([_lt_decl_filter],
++[m4_case([$#],
++ [0], [m4_fatal([$0: too few arguments: $#])],
++ [1], [m4_fatal([$0: too few arguments: $#: $1])],
++ [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)],
++ [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)],
++ [lt_dict_filter([lt_decl_dict], $@)])[]dnl
++])
++
++
++# lt_decl_quote_varnames([SEPARATOR], [VARNAME1...])
++# --------------------------------------------------
++m4_define([lt_decl_quote_varnames],
++[_lt_decl_filter([value], [1], $@)])
++
++
++# lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...])
++# ---------------------------------------------------
++m4_define([lt_decl_dquote_varnames],
++[_lt_decl_filter([value], [2], $@)])
++
++
++# lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...])
++# ---------------------------------------------------
++m4_define([lt_decl_varnames_tagged],
++[m4_assert([$# <= 2])dnl
++_$0(m4_quote(m4_default([$1], [[, ]])),
++ m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]),
++ m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))])
++m4_define([_lt_decl_varnames_tagged],
++[m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])])
++
++
++# lt_decl_all_varnames([SEPARATOR], [VARNAME1...])
++# ------------------------------------------------
++m4_define([lt_decl_all_varnames],
++[_$0(m4_quote(m4_default([$1], [[, ]])),
++ m4_if([$2], [],
++ m4_quote(lt_decl_varnames),
++ m4_quote(m4_shift($@))))[]dnl
++])
++m4_define([_lt_decl_all_varnames],
++[lt_join($@, lt_decl_varnames_tagged([$1],
++ lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl
++])
++
++
++# _LT_CONFIG_STATUS_DECLARE([VARNAME])
++# ------------------------------------
++# Quote a variable value, and forward it to 'config.status' so that its
++# declaration there will have the same value as in 'configure'. VARNAME
++# must have a single quote delimited value for this to work.
++m4_define([_LT_CONFIG_STATUS_DECLARE],
++[$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`'])
++
++
++# _LT_CONFIG_STATUS_DECLARATIONS
++# ------------------------------
++# We delimit libtool config variables with single quotes, so when
++# we write them to config.status, we have to be sure to quote all
++# embedded single quotes properly. In configure, this macro expands
++# each variable declared with _LT_DECL (and _LT_TAGDECL) into:
++#
++# <var>='`$ECHO "$<var>" | $SED "$delay_single_quote_subst"`'
++m4_defun([_LT_CONFIG_STATUS_DECLARATIONS],
++[m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames),
++ [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])])
++
++
++# _LT_LIBTOOL_TAGS
++# ----------------
++# Output comment and list of tags supported by the script
++m4_defun([_LT_LIBTOOL_TAGS],
++[_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl
++available_tags='_LT_TAGS'dnl
++])
++
++
++# _LT_LIBTOOL_DECLARE(VARNAME, [TAG])
++# -----------------------------------
++# Extract the dictionary values for VARNAME (optionally with TAG) and
++# expand to a commented shell variable setting:
++#
++# # Some comment about what VAR is for.
++# visible_name=$lt_internal_name
++m4_define([_LT_LIBTOOL_DECLARE],
++[_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1],
++ [description])))[]dnl
++m4_pushdef([_libtool_name],
++ m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl
++m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])),
++ [0], [_libtool_name=[$]$1],
++ [1], [_libtool_name=$lt_[]$1],
++ [2], [_libtool_name=$lt_[]$1],
++ [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl
++m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl
++])
++
++
++# _LT_LIBTOOL_CONFIG_VARS
++# -----------------------
++# Produce commented declarations of non-tagged libtool config variables
++# suitable for insertion in the LIBTOOL CONFIG section of the 'libtool'
++# script. Tagged libtool config variables (even for the LIBTOOL CONFIG
++# section) are produced by _LT_LIBTOOL_TAG_VARS.
++m4_defun([_LT_LIBTOOL_CONFIG_VARS],
++[m4_foreach([_lt_var],
++ m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)),
++ [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])])
++
++
++# _LT_LIBTOOL_TAG_VARS(TAG)
++# -------------------------
++m4_define([_LT_LIBTOOL_TAG_VARS],
++[m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames),
++ [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])])
++
++
++# _LT_TAGVAR(VARNAME, [TAGNAME])
++# ------------------------------
++m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])])
++
++
++# _LT_CONFIG_COMMANDS
++# -------------------
++# Send accumulated output to $CONFIG_STATUS. Thanks to the lists of
++# variables for single and double quote escaping we saved from calls
++# to _LT_DECL, we can put quote escaped variables declarations
++# into 'config.status', and then the shell code to quote escape them in
++# for loops in 'config.status'. Finally, any additional code accumulated
++# from calls to _LT_CONFIG_LIBTOOL_INIT is expanded.
++m4_defun([_LT_CONFIG_COMMANDS],
++[AC_PROVIDE_IFELSE([LT_OUTPUT],
++ dnl If the libtool generation code has been placed in $CONFIG_LT,
++ dnl instead of duplicating it all over again into config.status,
++ dnl then we will have config.status run $CONFIG_LT later, so it
++ dnl needs to know what name is stored there:
++ [AC_CONFIG_COMMANDS([libtool],
++ [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])],
++ dnl If the libtool generation code is destined for config.status,
++ dnl expand the accumulated commands and init code now:
++ [AC_CONFIG_COMMANDS([libtool],
++ [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])])
++])#_LT_CONFIG_COMMANDS
++
++
++# Initialize.
++m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT],
++[
++
++# The HP-UX ksh and POSIX shell print the target directory to stdout
++# if CDPATH is set.
++(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
++
++sed_quote_subst='$sed_quote_subst'
++double_quote_subst='$double_quote_subst'
++delay_variable_subst='$delay_variable_subst'
++_LT_CONFIG_STATUS_DECLARATIONS
++LTCC='$LTCC'
++LTCFLAGS='$LTCFLAGS'
++compiler='$compiler_DEFAULT'
++
++# A function that is used when there is no print builtin or printf.
++func_fallback_echo ()
++{
++ eval 'cat <<_LTECHO_EOF
++\$[]1
++_LTECHO_EOF'
++}
++
++# Quote evaled strings.
++for var in lt_decl_all_varnames([[ \
++]], lt_decl_quote_varnames); do
++ case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
++ *[[\\\\\\\`\\"\\\$]]*)
++ eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes
++ ;;
++ *)
++ eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
++ ;;
++ esac
++done
++
++# Double-quote double-evaled strings.
++for var in lt_decl_all_varnames([[ \
++]], lt_decl_dquote_varnames); do
++ case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
++ *[[\\\\\\\`\\"\\\$]]*)
++ eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes
++ ;;
++ *)
++ eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
++ ;;
++ esac
++done
++
++_LT_OUTPUT_LIBTOOL_INIT
++])
++
++# _LT_GENERATED_FILE_INIT(FILE, [COMMENT])
++# ------------------------------------
++# Generate a child script FILE with all initialization necessary to
++# reuse the environment learned by the parent script, and make the
++# file executable. If COMMENT is supplied, it is inserted after the
++# '#!' sequence but before initialization text begins. After this
++# macro, additional text can be appended to FILE to form the body of
++# the child script. The macro ends with non-zero status if the
++# file could not be fully written (such as if the disk is full).
++m4_ifdef([AS_INIT_GENERATED],
++[m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])],
++[m4_defun([_LT_GENERATED_FILE_INIT],
++[m4_require([AS_PREPARE])]dnl
++[m4_pushdef([AS_MESSAGE_LOG_FD])]dnl
++[lt_write_fail=0
++cat >$1 <<_ASEOF || lt_write_fail=1
++#! $SHELL
++# Generated by $as_me.
++$2
++SHELL=\${CONFIG_SHELL-$SHELL}
++export SHELL
++_ASEOF
++cat >>$1 <<\_ASEOF || lt_write_fail=1
++AS_SHELL_SANITIZE
++_AS_PREPARE
++exec AS_MESSAGE_FD>&1
++_ASEOF
++test 0 = "$lt_write_fail" && chmod +x $1[]dnl
++m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT
++
++# LT_OUTPUT
++# ---------
++# This macro allows early generation of the libtool script (before
++# AC_OUTPUT is called), incase it is used in configure for compilation
++# tests.
++AC_DEFUN([LT_OUTPUT],
++[: ${CONFIG_LT=./config.lt}
++AC_MSG_NOTICE([creating $CONFIG_LT])
++_LT_GENERATED_FILE_INIT(["$CONFIG_LT"],
++[# Run this file to recreate a libtool stub with the current configuration.])
++
++cat >>"$CONFIG_LT" <<\_LTEOF
++lt_cl_silent=false
++exec AS_MESSAGE_LOG_FD>>config.log
++{
++ echo
++ AS_BOX([Running $as_me.])
++} >&AS_MESSAGE_LOG_FD
++
++lt_cl_help="\
++'$as_me' creates a local libtool stub from the current configuration,
++for use in further configure time tests before the real libtool is
++generated.
++
++Usage: $[0] [[OPTIONS]]
++
++ -h, --help print this help, then exit
++ -V, --version print version number, then exit
++ -q, --quiet do not print progress messages
++ -d, --debug don't remove temporary files
++
++Report bugs to <bug-libtool@gnu.org>."
++
++lt_cl_version="\
++m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl
++m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION])
++configured by $[0], generated by m4_PACKAGE_STRING.
++
++Copyright (C) 2011 Free Software Foundation, Inc.
++This config.lt script is free software; the Free Software Foundation
++gives unlimited permision to copy, distribute and modify it."
++
++while test 0 != $[#]
++do
++ case $[1] in
++ --version | --v* | -V )
++ echo "$lt_cl_version"; exit 0 ;;
++ --help | --h* | -h )
++ echo "$lt_cl_help"; exit 0 ;;
++ --debug | --d* | -d )
++ debug=: ;;
++ --quiet | --q* | --silent | --s* | -q )
++ lt_cl_silent=: ;;
++
++ -*) AC_MSG_ERROR([unrecognized option: $[1]
++Try '$[0] --help' for more information.]) ;;
++
++ *) AC_MSG_ERROR([unrecognized argument: $[1]
++Try '$[0] --help' for more information.]) ;;
++ esac
++ shift
++done
++
++if $lt_cl_silent; then
++ exec AS_MESSAGE_FD>/dev/null
++fi
++_LTEOF
++
++cat >>"$CONFIG_LT" <<_LTEOF
++_LT_OUTPUT_LIBTOOL_COMMANDS_INIT
++_LTEOF
++
++cat >>"$CONFIG_LT" <<\_LTEOF
++AC_MSG_NOTICE([creating $ofile])
++_LT_OUTPUT_LIBTOOL_COMMANDS
++AS_EXIT(0)
++_LTEOF
++chmod +x "$CONFIG_LT"
++
++# configure is writing to config.log, but config.lt does its own redirection,
++# appending to config.log, which fails on DOS, as config.log is still kept
++# open by configure. Here we exec the FD to /dev/null, effectively closing
++# config.log, so it can be properly (re)opened and appended to by config.lt.
++lt_cl_success=:
++test yes = "$silent" &&
++ lt_config_lt_args="$lt_config_lt_args --quiet"
++exec AS_MESSAGE_LOG_FD>/dev/null
++$SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false
++exec AS_MESSAGE_LOG_FD>>config.log
++$lt_cl_success || AS_EXIT(1)
++])# LT_OUTPUT
++
++
++# _LT_CONFIG(TAG)
++# ---------------
++# If TAG is the built-in tag, create an initial libtool script with a
++# default configuration from the untagged config vars. Otherwise add code
++# to config.status for appending the configuration named by TAG from the
++# matching tagged config vars.
++m4_defun([_LT_CONFIG],
++[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
++_LT_CONFIG_SAVE_COMMANDS([
++ m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl
++ m4_if(_LT_TAG, [C], [
++ # See if we are running on zsh, and set the options that allow our
++ # commands through without removal of \ escapes.
++ if test -n "${ZSH_VERSION+set}"; then
++ setopt NO_GLOB_SUBST
++ fi
++
++ cfgfile=${ofile}T
++ trap "$RM \"$cfgfile\"; exit 1" 1 2 15
++ $RM "$cfgfile"
++
++ cat <<_LT_EOF >> "$cfgfile"
++#! $SHELL
++# Generated automatically by $as_me ($PACKAGE) $VERSION
++# NOTE: Changes made to this file will be lost: look at ltmain.sh.
++
++# Provide generalized library-building support services.
++# Written by Gordon Matzigkeit, 1996
++
++_LT_COPYING
++_LT_LIBTOOL_TAGS
++
++# Configured defaults for sys_lib_dlsearch_path munging.
++: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"}
++
++# ### BEGIN LIBTOOL CONFIG
++_LT_LIBTOOL_CONFIG_VARS
++_LT_LIBTOOL_TAG_VARS
++# ### END LIBTOOL CONFIG
++
++_LT_EOF
++
++ cat <<'_LT_EOF' >> "$cfgfile"
++
++# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE
++
++_LT_PREPARE_MUNGE_PATH_LIST
++_LT_PREPARE_CC_BASENAME
++
++# ### END FUNCTIONS SHARED WITH CONFIGURE
++
++_LT_EOF
++
++ case $host_os in
++ aix3*)
++ cat <<\_LT_EOF >> "$cfgfile"
++# AIX sometimes has problems with the GCC collect2 program. For some
++# reason, if we set the COLLECT_NAMES environment variable, the problems
++# vanish in a puff of smoke.
++if test set != "${COLLECT_NAMES+set}"; then
++ COLLECT_NAMES=
++ export COLLECT_NAMES
++fi
++_LT_EOF
++ ;;
++ esac
++
++ _LT_PROG_LTMAIN
++
++ # We use sed instead of cat because bash on DJGPP gets confused if
++ # if finds mixed CR/LF and LF-only lines. Since sed operates in
++ # text mode, it properly converts lines to CR/LF. This bash problem
++ # is reportedly fixed, but why not run on old versions too?
++ $SED '$q' "$ltmain" >> "$cfgfile" \
++ || (rm -f "$cfgfile"; exit 1)
++
++ mv -f "$cfgfile" "$ofile" ||
++ (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
++ chmod +x "$ofile"
++],
++[cat <<_LT_EOF >> "$ofile"
++
++dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded
++dnl in a comment (ie after a #).
++# ### BEGIN LIBTOOL TAG CONFIG: $1
++_LT_LIBTOOL_TAG_VARS(_LT_TAG)
++# ### END LIBTOOL TAG CONFIG: $1
++_LT_EOF
++])dnl /m4_if
++],
++[m4_if([$1], [], [
++ PACKAGE='$PACKAGE'
++ VERSION='$VERSION'
++ RM='$RM'
++ ofile='$ofile'], [])
++])dnl /_LT_CONFIG_SAVE_COMMANDS
++])# _LT_CONFIG
++
++
++# LT_SUPPORTED_TAG(TAG)
++# ---------------------
++# Trace this macro to discover what tags are supported by the libtool
++# --tag option, using:
++# autoconf --trace 'LT_SUPPORTED_TAG:$1'
++AC_DEFUN([LT_SUPPORTED_TAG], [])
++
++
++# C support is built-in for now
++m4_define([_LT_LANG_C_enabled], [])
++m4_define([_LT_TAGS], [])
++
++
++# LT_LANG(LANG)
++# -------------
++# Enable libtool support for the given language if not already enabled.
++AC_DEFUN([LT_LANG],
++[AC_BEFORE([$0], [LT_OUTPUT])dnl
++m4_case([$1],
++ [C], [_LT_LANG(C)],
++ [C++], [_LT_LANG(CXX)],
++ [Go], [_LT_LANG(GO)],
++ [Java], [_LT_LANG(GCJ)],
++ [Fortran 77], [_LT_LANG(F77)],
++ [Fortran], [_LT_LANG(FC)],
++ [Windows Resource], [_LT_LANG(RC)],
++ [m4_ifdef([_LT_LANG_]$1[_CONFIG],
++ [_LT_LANG($1)],
++ [m4_fatal([$0: unsupported language: "$1"])])])dnl
++])# LT_LANG
++
++
++# _LT_LANG(LANGNAME)
++# ------------------
++m4_defun([_LT_LANG],
++[m4_ifdef([_LT_LANG_]$1[_enabled], [],
++ [LT_SUPPORTED_TAG([$1])dnl
++ m4_append([_LT_TAGS], [$1 ])dnl
++ m4_define([_LT_LANG_]$1[_enabled], [])dnl
++ _LT_LANG_$1_CONFIG($1)])dnl
++])# _LT_LANG
++
++
++m4_ifndef([AC_PROG_GO], [
++# NOTE: This macro has been submitted for inclusion into #
++# GNU Autoconf as AC_PROG_GO. When it is available in #
++# a released version of Autoconf we should remove this #
++# macro and use it instead. #
++m4_defun([AC_PROG_GO],
++[AC_LANG_PUSH(Go)dnl
++AC_ARG_VAR([GOC], [Go compiler command])dnl
++AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl
++_AC_ARG_VAR_LDFLAGS()dnl
++AC_CHECK_TOOL(GOC, gccgo)
++if test -z "$GOC"; then
++ if test -n "$ac_tool_prefix"; then
++ AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo])
++ fi
++fi
++if test -z "$GOC"; then
++ AC_CHECK_PROG(GOC, gccgo, gccgo, false)
++fi
++])#m4_defun
++])#m4_ifndef
++
++
++# _LT_LANG_DEFAULT_CONFIG
++# -----------------------
++m4_defun([_LT_LANG_DEFAULT_CONFIG],
++[AC_PROVIDE_IFELSE([AC_PROG_CXX],
++ [LT_LANG(CXX)],
++ [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])])
++
++AC_PROVIDE_IFELSE([AC_PROG_F77],
++ [LT_LANG(F77)],
++ [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])])
++
++AC_PROVIDE_IFELSE([AC_PROG_FC],
++ [LT_LANG(FC)],
++ [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])])
++
++dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal
++dnl pulling things in needlessly.
++AC_PROVIDE_IFELSE([AC_PROG_GCJ],
++ [LT_LANG(GCJ)],
++ [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],
++ [LT_LANG(GCJ)],
++ [AC_PROVIDE_IFELSE([LT_PROG_GCJ],
++ [LT_LANG(GCJ)],
++ [m4_ifdef([AC_PROG_GCJ],
++ [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])])
++ m4_ifdef([A][M_PROG_GCJ],
++ [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])])
++ m4_ifdef([LT_PROG_GCJ],
++ [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])])
++
++AC_PROVIDE_IFELSE([AC_PROG_GO],
++ [LT_LANG(GO)],
++ [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])])
++
++AC_PROVIDE_IFELSE([LT_PROG_RC],
++ [LT_LANG(RC)],
++ [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])])
++])# _LT_LANG_DEFAULT_CONFIG
++
++# Obsolete macros:
++AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)])
++AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)])
++AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)])
++AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)])
++AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)])
++dnl aclocal-1.4 backwards compatibility:
++dnl AC_DEFUN([AC_LIBTOOL_CXX], [])
++dnl AC_DEFUN([AC_LIBTOOL_F77], [])
++dnl AC_DEFUN([AC_LIBTOOL_FC], [])
++dnl AC_DEFUN([AC_LIBTOOL_GCJ], [])
++dnl AC_DEFUN([AC_LIBTOOL_RC], [])
++
++
++# _LT_TAG_COMPILER
++# ----------------
++m4_defun([_LT_TAG_COMPILER],
++[AC_REQUIRE([AC_PROG_CC])dnl
++
++_LT_DECL([LTCC], [CC], [1], [A C compiler])dnl
++_LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl
++_LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl
++_LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl
++
++# If no C compiler was specified, use CC.
++LTCC=${LTCC-"$CC"}
++
++# If no C compiler flags were specified, use CFLAGS.
++LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
++
++# Allow CC to be a program name with arguments.
++compiler=$CC
++])# _LT_TAG_COMPILER
++
++
++# _LT_COMPILER_BOILERPLATE
++# ------------------------
++# Check for compiler boilerplate output or warnings with
++# the simple compiler test code.
++m4_defun([_LT_COMPILER_BOILERPLATE],
++[m4_require([_LT_DECL_SED])dnl
++ac_outfile=conftest.$ac_objext
++echo "$lt_simple_compile_test_code" >conftest.$ac_ext
++eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
++_lt_compiler_boilerplate=`cat conftest.err`
++$RM conftest*
++])# _LT_COMPILER_BOILERPLATE
++
++
++# _LT_LINKER_BOILERPLATE
++# ----------------------
++# Check for linker boilerplate output or warnings with
++# the simple link test code.
++m4_defun([_LT_LINKER_BOILERPLATE],
++[m4_require([_LT_DECL_SED])dnl
++ac_outfile=conftest.$ac_objext
++echo "$lt_simple_link_test_code" >conftest.$ac_ext
++eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
++_lt_linker_boilerplate=`cat conftest.err`
++$RM -r conftest*
++])# _LT_LINKER_BOILERPLATE
++
++# _LT_REQUIRED_DARWIN_CHECKS
++# -------------------------
++m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[
++ case $host_os in
++ rhapsody* | darwin*)
++ AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:])
++ AC_CHECK_TOOL([NMEDIT], [nmedit], [:])
++ AC_CHECK_TOOL([LIPO], [lipo], [:])
++ AC_CHECK_TOOL([OTOOL], [otool], [:])
++ AC_CHECK_TOOL([OTOOL64], [otool64], [:])
++ _LT_DECL([], [DSYMUTIL], [1],
++ [Tool to manipulate archived DWARF debug symbol files on Mac OS X])
++ _LT_DECL([], [NMEDIT], [1],
++ [Tool to change global to local symbols on Mac OS X])
++ _LT_DECL([], [LIPO], [1],
++ [Tool to manipulate fat objects and archives on Mac OS X])
++ _LT_DECL([], [OTOOL], [1],
++ [ldd/readelf like tool for Mach-O binaries on Mac OS X])
++ _LT_DECL([], [OTOOL64], [1],
++ [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4])
++
++ AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod],
++ [lt_cv_apple_cc_single_mod=no
++ if test -z "$LT_MULTI_MODULE"; then
++ # By default we will add the -single_module flag. You can override
++ # by either setting the environment variable LT_MULTI_MODULE
++ # non-empty at configure time, or by adding -multi_module to the
++ # link flags.
++ rm -rf libconftest.dylib*
++ echo "int foo(void){return 1;}" > conftest.c
++ echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
++-dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD
++ $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
++ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err
++ _lt_result=$?
++ # If there is a non-empty error log, and "single_module"
++ # appears in it, assume the flag caused a linker warning
++ if test -s conftest.err && $GREP single_module conftest.err; then
++ cat conftest.err >&AS_MESSAGE_LOG_FD
++ # Otherwise, if the output was created with a 0 exit code from
++ # the compiler, it worked.
++ elif test -f libconftest.dylib && test 0 = "$_lt_result"; then
++ lt_cv_apple_cc_single_mod=yes
++ else
++ cat conftest.err >&AS_MESSAGE_LOG_FD
++ fi
++ rm -rf libconftest.dylib*
++ rm -f conftest.*
++ fi])
++
++ AC_CACHE_CHECK([for -exported_symbols_list linker flag],
++ [lt_cv_ld_exported_symbols_list],
++ [lt_cv_ld_exported_symbols_list=no
++ save_LDFLAGS=$LDFLAGS
++ echo "_main" > conftest.sym
++ LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym"
++ AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])],
++ [lt_cv_ld_exported_symbols_list=yes],
++ [lt_cv_ld_exported_symbols_list=no])
++ LDFLAGS=$save_LDFLAGS
++ ])
++
++ AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load],
++ [lt_cv_ld_force_load=no
++ cat > conftest.c << _LT_EOF
++int forced_loaded() { return 2;}
++_LT_EOF
++ echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD
++ $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD
++ echo "$AR $AR_FLAGS libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD
++ $AR $AR_FLAGS libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD
++ echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD
++ $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD
++ cat > conftest.c << _LT_EOF
++int main() { return 0;}
++_LT_EOF
++ echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD
++ $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err
++ _lt_result=$?
++ if test -s conftest.err && $GREP force_load conftest.err; then
++ cat conftest.err >&AS_MESSAGE_LOG_FD
++ elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then
++ lt_cv_ld_force_load=yes
++ else
++ cat conftest.err >&AS_MESSAGE_LOG_FD
++ fi
++ rm -f conftest.err libconftest.a conftest conftest.c
++ rm -rf conftest.dSYM
++ ])
++ case $host_os in
++ rhapsody* | darwin1.[[012]])
++ _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;;
++ darwin1.*)
++ _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
++ darwin*)
++ case $MACOSX_DEPLOYMENT_TARGET,$host in
++ 10.[[012]],*|,*powerpc*-darwin[[5-8]]*)
++ _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
++ *)
++ _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;;
++ esac
++ ;;
++ esac
++ if test yes = "$lt_cv_apple_cc_single_mod"; then
++ _lt_dar_single_mod='$single_module'
++ fi
++ if test yes = "$lt_cv_ld_exported_symbols_list"; then
++ _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym'
++ else
++ _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib'
++ fi
++ if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then
++ _lt_dsymutil='~$DSYMUTIL $lib || :'
++ else
++ _lt_dsymutil=
++ fi
++ ;;
++ esac
++])
++
++
++# _LT_DARWIN_LINKER_FEATURES([TAG])
++# ---------------------------------
++# Checks for linker and compiler features on darwin
++m4_defun([_LT_DARWIN_LINKER_FEATURES],
++[
++ m4_require([_LT_REQUIRED_DARWIN_CHECKS])
++ _LT_TAGVAR(archive_cmds_need_lc, $1)=no
++ _LT_TAGVAR(hardcode_direct, $1)=no
++ _LT_TAGVAR(hardcode_automatic, $1)=yes
++ _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
++ if test yes = "$lt_cv_ld_force_load"; then
++ _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`'
++ m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes],
++ [FC], [_LT_TAGVAR(compiler_needs_object, $1)=yes])
++ else
++ _LT_TAGVAR(whole_archive_flag_spec, $1)=''
++ fi
++ _LT_TAGVAR(link_all_deplibs, $1)=yes
++ _LT_TAGVAR(allow_undefined_flag, $1)=$_lt_dar_allow_undefined
++ case $cc_basename in
++ ifort*|nagfor*) _lt_dar_can_shared=yes ;;
++ *) _lt_dar_can_shared=$GCC ;;
++ esac
++ if test yes = "$_lt_dar_can_shared"; then
++ output_verbose_link_cmd=func_echo_all
++ _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil"
++ _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil"
++ _LT_TAGVAR(archive_expsym_cmds, $1)="$SED 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil"
++ _LT_TAGVAR(module_expsym_cmds, $1)="$SED -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil"
++ m4_if([$1], [CXX],
++[ if test yes != "$lt_cv_apple_cc_single_mod"; then
++ _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil"
++ _LT_TAGVAR(archive_expsym_cmds, $1)="$SED 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil"
++ fi
++],[])
++ else
++ _LT_TAGVAR(ld_shlibs, $1)=no
++ fi
++])
++
++# _LT_SYS_MODULE_PATH_AIX([TAGNAME])
++# ----------------------------------
++# Links a minimal program and checks the executable
++# for the system default hardcoded library path. In most cases,
++# this is /usr/lib:/lib, but when the MPI compilers are used
++# the location of the communication and MPI libs are included too.
++# If we don't find anything, use the default library path according
++# to the aix ld manual.
++# Store the results from the different compilers for each TAGNAME.
++# Allow to override them for all tags through lt_cv_aix_libpath.
++m4_defun([_LT_SYS_MODULE_PATH_AIX],
++[m4_require([_LT_DECL_SED])dnl
++if test set = "${lt_cv_aix_libpath+set}"; then
++ aix_libpath=$lt_cv_aix_libpath
++else
++ AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])],
++ [AC_LINK_IFELSE([AC_LANG_PROGRAM],[
++ lt_aix_libpath_sed='[
++ /Import File Strings/,/^$/ {
++ /^0/ {
++ s/^0 *\([^ ]*\) *$/\1/
++ p
++ }
++ }]'
++ _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
++ # Check for a 64-bit object if we didn't find anything.
++ if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then
++ _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
++ fi],[])
++ if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then
++ _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=/usr/lib:/lib
++ fi
++ ])
++ aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])
++fi
++])# _LT_SYS_MODULE_PATH_AIX
++
++
++# _LT_SHELL_INIT(ARG)
++# -------------------
++m4_define([_LT_SHELL_INIT],
++[m4_divert_text([M4SH-INIT], [$1
++])])# _LT_SHELL_INIT
++
++
++
++# _LT_PROG_ECHO_BACKSLASH
++# -----------------------
++# Find how we can fake an echo command that does not interpret backslash.
++# In particular, with Autoconf 2.60 or later we add some code to the start
++# of the generated configure script that will find a shell with a builtin
++# printf (that we can use as an echo command).
++m4_defun([_LT_PROG_ECHO_BACKSLASH],
++[ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
++ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO
++ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO
++
++AC_MSG_CHECKING([how to print strings])
++# Test print first, because it will be a builtin if present.
++if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \
++ test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then
++ ECHO='print -r --'
++elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then
++ ECHO='printf %s\n'
++else
++ # Use this function as a fallback that always works.
++ func_fallback_echo ()
++ {
++ eval 'cat <<_LTECHO_EOF
++$[]1
++_LTECHO_EOF'
++ }
++ ECHO='func_fallback_echo'
++fi
++
++# func_echo_all arg...
++# Invoke $ECHO with all args, space-separated.
++func_echo_all ()
++{
++ $ECHO "$*"
++}
++
++case $ECHO in
++ printf*) AC_MSG_RESULT([printf]) ;;
++ print*) AC_MSG_RESULT([print -r]) ;;
++ *) AC_MSG_RESULT([cat]) ;;
++esac
++
++m4_ifdef([_AS_DETECT_SUGGESTED],
++[_AS_DETECT_SUGGESTED([
++ test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || (
++ ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
++ ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO
++ ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO
++ PATH=/empty FPATH=/empty; export PATH FPATH
++ test "X`printf %s $ECHO`" = "X$ECHO" \
++ || test "X`print -r -- $ECHO`" = "X$ECHO" )])])
++
++_LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts])
++_LT_DECL([], [ECHO], [1], [An echo program that protects backslashes])
++])# _LT_PROG_ECHO_BACKSLASH
++
++
++# _LT_WITH_SYSROOT
++# ----------------
++AC_DEFUN([_LT_WITH_SYSROOT],
++[m4_require([_LT_DECL_SED])dnl
++AC_MSG_CHECKING([for sysroot])
++AC_ARG_WITH([sysroot],
++[AS_HELP_STRING([--with-sysroot@<:@=DIR@:>@],
++ [Search for dependent libraries within DIR (or the compiler's sysroot
++ if not specified).])],
++[], [with_sysroot=no])
++
++dnl lt_sysroot will always be passed unquoted. We quote it here
++dnl in case the user passed a directory name.
++lt_sysroot=
++case $with_sysroot in #(
++ yes)
++ if test yes = "$GCC"; then
++ lt_sysroot=`$CC --print-sysroot 2>/dev/null`
++ fi
++ ;; #(
++ /*)
++ lt_sysroot=`echo "$with_sysroot" | $SED -e "$sed_quote_subst"`
++ ;; #(
++ no|'')
++ ;; #(
++ *)
++ AC_MSG_RESULT([$with_sysroot])
++ AC_MSG_ERROR([The sysroot must be an absolute path.])
++ ;;
++esac
++
++ AC_MSG_RESULT([${lt_sysroot:-no}])
++_LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl
++[dependent libraries, and where our libraries should be installed.])])
++
++# _LT_ENABLE_LOCK
++# ---------------
++m4_defun([_LT_ENABLE_LOCK],
++[AC_ARG_ENABLE([libtool-lock],
++ [AS_HELP_STRING([--disable-libtool-lock],
++ [avoid locking (might break parallel builds)])])
++test no = "$enable_libtool_lock" || enable_libtool_lock=yes
++
++# Some flags need to be propagated to the compiler or linker for good
++# libtool support.
++case $host in
++ia64-*-hpux*)
++ # Find out what ABI is being produced by ac_compile, and set mode
++ # options accordingly.
++ echo 'int i;' > conftest.$ac_ext
++ if AC_TRY_EVAL(ac_compile); then
++ case `$FILECMD conftest.$ac_objext` in
++ *ELF-32*)
++ HPUX_IA64_MODE=32
++ ;;
++ *ELF-64*)
++ HPUX_IA64_MODE=64
++ ;;
++ esac
++ fi
++ rm -rf conftest*
++ ;;
++*-*-irix6*)
++ # Find out what ABI is being produced by ac_compile, and set linker
++ # options accordingly.
++ echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext
++ if AC_TRY_EVAL(ac_compile); then
++ if test yes = "$lt_cv_prog_gnu_ld"; then
++ case `$FILECMD conftest.$ac_objext` in
++ *32-bit*)
++ LD="${LD-ld} -melf32bsmip"
++ ;;
++ *N32*)
++ LD="${LD-ld} -melf32bmipn32"
++ ;;
++ *64-bit*)
++ LD="${LD-ld} -melf64bmip"
++ ;;
++ esac
++ else
++ case `$FILECMD conftest.$ac_objext` in
++ *32-bit*)
++ LD="${LD-ld} -32"
++ ;;
++ *N32*)
++ LD="${LD-ld} -n32"
++ ;;
++ *64-bit*)
++ LD="${LD-ld} -64"
++ ;;
++ esac
++ fi
++ fi
++ rm -rf conftest*
++ ;;
++
++mips64*-*linux*)
++ # Find out what ABI is being produced by ac_compile, and set linker
++ # options accordingly.
++ echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext
++ if AC_TRY_EVAL(ac_compile); then
++ emul=elf
++ case `$FILECMD conftest.$ac_objext` in
++ *32-bit*)
++ emul="${emul}32"
++ ;;
++ *64-bit*)
++ emul="${emul}64"
++ ;;
++ esac
++ case `$FILECMD conftest.$ac_objext` in
++ *MSB*)
++ emul="${emul}btsmip"
++ ;;
++ *LSB*)
++ emul="${emul}ltsmip"
++ ;;
++ esac
++ case `$FILECMD conftest.$ac_objext` in
++ *N32*)
++ emul="${emul}n32"
++ ;;
++ esac
++ LD="${LD-ld} -m $emul"
++ fi
++ rm -rf conftest*
++ ;;
++
++x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \
++s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
++ # Find out what ABI is being produced by ac_compile, and set linker
++ # options accordingly. Note that the listed cases only cover the
++ # situations where additional linker options are needed (such as when
++ # doing 32-bit compilation for a host where ld defaults to 64-bit, or
++ # vice versa); the common cases where no linker options are needed do
++ # not appear in the list.
++ echo 'int i;' > conftest.$ac_ext
++ if AC_TRY_EVAL(ac_compile); then
++ case `$FILECMD conftest.o` in
++ *32-bit*)
++ case $host in
++ x86_64-*kfreebsd*-gnu)
++ LD="${LD-ld} -m elf_i386_fbsd"
++ ;;
++ x86_64-*linux*)
++ case `$FILECMD conftest.o` in
++ *x86-64*)
++ LD="${LD-ld} -m elf32_x86_64"
++ ;;
++ *)
++ LD="${LD-ld} -m elf_i386"
++ ;;
++ esac
++ ;;
++ powerpc64le-*linux*)
++ LD="${LD-ld} -m elf32lppclinux"
++ ;;
++ powerpc64-*linux*)
++ LD="${LD-ld} -m elf32ppclinux"
++ ;;
++ s390x-*linux*)
++ LD="${LD-ld} -m elf_s390"
++ ;;
++ sparc64-*linux*)
++ LD="${LD-ld} -m elf32_sparc"
++ ;;
++ esac
++ ;;
++ *64-bit*)
++ case $host in
++ x86_64-*kfreebsd*-gnu)
++ LD="${LD-ld} -m elf_x86_64_fbsd"
++ ;;
++ x86_64-*linux*)
++ LD="${LD-ld} -m elf_x86_64"
++ ;;
++ powerpcle-*linux*)
++ LD="${LD-ld} -m elf64lppc"
++ ;;
++ powerpc-*linux*)
++ LD="${LD-ld} -m elf64ppc"
++ ;;
++ s390*-*linux*|s390*-*tpf*)
++ LD="${LD-ld} -m elf64_s390"
++ ;;
++ sparc*-*linux*)
++ LD="${LD-ld} -m elf64_sparc"
++ ;;
++ esac
++ ;;
++ esac
++ fi
++ rm -rf conftest*
++ ;;
++
++*-*-sco3.2v5*)
++ # On SCO OpenServer 5, we need -belf to get full-featured binaries.
++ SAVE_CFLAGS=$CFLAGS
++ CFLAGS="$CFLAGS -belf"
++ AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf,
++ [AC_LANG_PUSH(C)
++ AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no])
++ AC_LANG_POP])
++ if test yes != "$lt_cv_cc_needs_belf"; then
++ # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
++ CFLAGS=$SAVE_CFLAGS
++ fi
++ ;;
++*-*solaris*)
++ # Find out what ABI is being produced by ac_compile, and set linker
++ # options accordingly.
++ echo 'int i;' > conftest.$ac_ext
++ if AC_TRY_EVAL(ac_compile); then
++ case `$FILECMD conftest.o` in
++ *64-bit*)
++ case $lt_cv_prog_gnu_ld in
++ yes*)
++ case $host in
++ i?86-*-solaris*|x86_64-*-solaris*)
++ LD="${LD-ld} -m elf_x86_64"
++ ;;
++ sparc*-*-solaris*)
++ LD="${LD-ld} -m elf64_sparc"
++ ;;
++ esac
++ # GNU ld 2.21 introduced _sol2 emulations. Use them if available.
++ if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then
++ LD=${LD-ld}_sol2
++ fi
++ ;;
++ *)
++ if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then
++ LD="${LD-ld} -64"
++ fi
++ ;;
++ esac
++ ;;
++ esac
++ fi
++ rm -rf conftest*
++ ;;
++esac
++
++need_locks=$enable_libtool_lock
++])# _LT_ENABLE_LOCK
++
++
++# _LT_PROG_AR
++# -----------
++m4_defun([_LT_PROG_AR],
++[AC_CHECK_TOOLS(AR, [ar], false)
++: ${AR=ar}
++_LT_DECL([], [AR], [1], [The archiver])
++
++# Use ARFLAGS variable as AR's operation code to sync the variable naming with
++# Automake. If both AR_FLAGS and ARFLAGS are specified, AR_FLAGS should have
++# higher priority because thats what people were doing historically (setting
++# ARFLAGS for automake and AR_FLAGS for libtool). FIXME: Make the AR_FLAGS
++# variable obsoleted/removed.
++
++test ${AR_FLAGS+y} || AR_FLAGS=${ARFLAGS-cr}
++lt_ar_flags=$AR_FLAGS
++_LT_DECL([], [lt_ar_flags], [0], [Flags to create an archive (by configure)])
++
++# Make AR_FLAGS overridable by 'make ARFLAGS='. Don't try to run-time override
++# by AR_FLAGS because that was never working and AR_FLAGS is about to die.
++_LT_DECL([], [AR_FLAGS], [\@S|@{ARFLAGS-"\@S|@lt_ar_flags"}],
++ [Flags to create an archive])
++
++AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file],
++ [lt_cv_ar_at_file=no
++ AC_COMPILE_IFELSE([AC_LANG_PROGRAM],
++ [echo conftest.$ac_objext > conftest.lst
++ lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD'
++ AC_TRY_EVAL([lt_ar_try])
++ if test 0 -eq "$ac_status"; then
++ # Ensure the archiver fails upon bogus file names.
++ rm -f conftest.$ac_objext libconftest.a
++ AC_TRY_EVAL([lt_ar_try])
++ if test 0 -ne "$ac_status"; then
++ lt_cv_ar_at_file=@
++ fi
++ fi
++ rm -f conftest.* libconftest.a
++ ])
++ ])
++
++if test no = "$lt_cv_ar_at_file"; then
++ archiver_list_spec=
++else
++ archiver_list_spec=$lt_cv_ar_at_file
++fi
++_LT_DECL([], [archiver_list_spec], [1],
++ [How to feed a file listing to the archiver])
++])# _LT_PROG_AR
++
++
++# _LT_CMD_OLD_ARCHIVE
++# -------------------
++m4_defun([_LT_CMD_OLD_ARCHIVE],
++[_LT_PROG_AR
++
++AC_CHECK_TOOL(STRIP, strip, :)
++test -z "$STRIP" && STRIP=:
++_LT_DECL([], [STRIP], [1], [A symbol stripping program])
++
++AC_CHECK_TOOL(RANLIB, ranlib, :)
++test -z "$RANLIB" && RANLIB=:
++_LT_DECL([], [RANLIB], [1],
++ [Commands used to install an old-style archive])
++
++# Determine commands to create old-style static archives.
++old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs'
++old_postinstall_cmds='chmod 644 $oldlib'
++old_postuninstall_cmds=
++
++if test -n "$RANLIB"; then
++ case $host_os in
++ bitrig* | openbsd*)
++ old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib"
++ ;;
++ *)
++ old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib"
++ ;;
++ esac
++ old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib"
++fi
++
++case $host_os in
++ darwin*)
++ lock_old_archive_extraction=yes ;;
++ *)
++ lock_old_archive_extraction=no ;;
++esac
++_LT_DECL([], [old_postinstall_cmds], [2])
++_LT_DECL([], [old_postuninstall_cmds], [2])
++_LT_TAGDECL([], [old_archive_cmds], [2],
++ [Commands used to build an old-style archive])
++_LT_DECL([], [lock_old_archive_extraction], [0],
++ [Whether to use a lock for old archive extraction])
++])# _LT_CMD_OLD_ARCHIVE
++
++
++# _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
++# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE])
++# ----------------------------------------------------------------
++# Check whether the given compiler option works
++AC_DEFUN([_LT_COMPILER_OPTION],
++[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
++m4_require([_LT_DECL_SED])dnl
++AC_CACHE_CHECK([$1], [$2],
++ [$2=no
++ m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4])
++ echo "$lt_simple_compile_test_code" > conftest.$ac_ext
++ lt_compiler_flag="$3" ## exclude from sc_useless_quotes_in_assignment
++ # Insert the option either (1) after the last *FLAGS variable, or
++ # (2) before a word containing "conftest.", or (3) at the end.
++ # Note that $ac_compile itself does not contain backslashes and begins
++ # with a dollar sign (not a hyphen), so the echo should work correctly.
++ # The option is referenced via a variable to avoid confusing sed.
++ lt_compile=`echo "$ac_compile" | $SED \
++ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
++ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
++ -e 's:$: $lt_compiler_flag:'`
++ (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
++ (eval "$lt_compile" 2>conftest.err)
++ ac_status=$?
++ cat conftest.err >&AS_MESSAGE_LOG_FD
++ echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
++ if (exit $ac_status) && test -s "$ac_outfile"; then
++ # The compiler can only warn and ignore the option if not recognized
++ # So say no if there are warnings other than the usual output.
++ $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp
++ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
++ if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
++ $2=yes
++ fi
++ fi
++ $RM conftest*
++])
++
++if test yes = "[$]$2"; then
++ m4_if([$5], , :, [$5])
++else
++ m4_if([$6], , :, [$6])
++fi
++])# _LT_COMPILER_OPTION
++
++# Old name:
++AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION])
++dnl aclocal-1.4 backwards compatibility:
++dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], [])
++
++
++# _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
++# [ACTION-SUCCESS], [ACTION-FAILURE])
++# ----------------------------------------------------
++# Check whether the given linker option works
++AC_DEFUN([_LT_LINKER_OPTION],
++[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
++m4_require([_LT_DECL_SED])dnl
++AC_CACHE_CHECK([$1], [$2],
++ [$2=no
++ save_LDFLAGS=$LDFLAGS
++ LDFLAGS="$LDFLAGS $3"
++ echo "$lt_simple_link_test_code" > conftest.$ac_ext
++ if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
++ # The linker can only warn and ignore the option if not recognized
++ # So say no if there are warnings
++ if test -s conftest.err; then
++ # Append any errors to the config.log.
++ cat conftest.err 1>&AS_MESSAGE_LOG_FD
++ $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp
++ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
++ if diff conftest.exp conftest.er2 >/dev/null; then
++ $2=yes
++ fi
++ else
++ $2=yes
++ fi
++ fi
++ $RM -r conftest*
++ LDFLAGS=$save_LDFLAGS
++])
++
++if test yes = "[$]$2"; then
++ m4_if([$4], , :, [$4])
++else
++ m4_if([$5], , :, [$5])
++fi
++])# _LT_LINKER_OPTION
++
++# Old name:
++AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION])
++dnl aclocal-1.4 backwards compatibility:
++dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], [])
++
++
++# LT_CMD_MAX_LEN
++#---------------
++AC_DEFUN([LT_CMD_MAX_LEN],
++[AC_REQUIRE([AC_CANONICAL_HOST])dnl
++# find the maximum length of command line arguments
++AC_MSG_CHECKING([the maximum length of command line arguments])
++AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl
++ i=0
++ teststring=ABCD
++
++ case $build_os in
++ msdosdjgpp*)
++ # On DJGPP, this test can blow up pretty badly due to problems in libc
++ # (any single argument exceeding 2000 bytes causes a buffer overrun
++ # during glob expansion). Even if it were fixed, the result of this
++ # check would be larger than it should be.
++ lt_cv_sys_max_cmd_len=12288; # 12K is about right
++ ;;
++
++ gnu*)
++ # Under GNU Hurd, this test is not required because there is
++ # no limit to the length of command line arguments.
++ # Libtool will interpret -1 as no limit whatsoever
++ lt_cv_sys_max_cmd_len=-1;
++ ;;
++
++ cygwin* | mingw* | cegcc*)
++ # On Win9x/ME, this test blows up -- it succeeds, but takes
++ # about 5 minutes as the teststring grows exponentially.
++ # Worse, since 9x/ME are not pre-emptively multitasking,
++ # you end up with a "frozen" computer, even though with patience
++ # the test eventually succeeds (with a max line length of 256k).
++ # Instead, let's just punt: use the minimum linelength reported by
++ # all of the supported platforms: 8192 (on NT/2K/XP).
++ lt_cv_sys_max_cmd_len=8192;
++ ;;
++
++ mint*)
++ # On MiNT this can take a long time and run out of memory.
++ lt_cv_sys_max_cmd_len=8192;
++ ;;
++
++ amigaos*)
++ # On AmigaOS with pdksh, this test takes hours, literally.
++ # So we just punt and use a minimum line length of 8192.
++ lt_cv_sys_max_cmd_len=8192;
++ ;;
++
++ bitrig* | darwin* | dragonfly* | freebsd* | midnightbsd* | netbsd* | openbsd*)
++ # This has been around since 386BSD, at least. Likely further.
++ if test -x /sbin/sysctl; then
++ lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
++ elif test -x /usr/sbin/sysctl; then
++ lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
++ else
++ lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs
++ fi
++ # And add a safety zone
++ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
++ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
++ ;;
++
++ interix*)
++ # We know the value 262144 and hardcode it with a safety zone (like BSD)
++ lt_cv_sys_max_cmd_len=196608
++ ;;
++
++ os2*)
++ # The test takes a long time on OS/2.
++ lt_cv_sys_max_cmd_len=8192
++ ;;
++
++ osf*)
++ # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure
++ # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not
++ # nice to cause kernel panics so lets avoid the loop below.
++ # First set a reasonable default.
++ lt_cv_sys_max_cmd_len=16384
++ #
++ if test -x /sbin/sysconfig; then
++ case `/sbin/sysconfig -q proc exec_disable_arg_limit` in
++ *1*) lt_cv_sys_max_cmd_len=-1 ;;
++ esac
++ fi
++ ;;
++ sco3.2v5*)
++ lt_cv_sys_max_cmd_len=102400
++ ;;
++ sysv5* | sco5v6* | sysv4.2uw2*)
++ kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
++ if test -n "$kargmax"; then
++ lt_cv_sys_max_cmd_len=`echo $kargmax | $SED 's/.*[[ ]]//'`
++ else
++ lt_cv_sys_max_cmd_len=32768
++ fi
++ ;;
++ *)
++ lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null`
++ if test -n "$lt_cv_sys_max_cmd_len" && \
++ test undefined != "$lt_cv_sys_max_cmd_len"; then
++ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
++ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
++ else
++ # Make teststring a little bigger before we do anything with it.
++ # a 1K string should be a reasonable start.
++ for i in 1 2 3 4 5 6 7 8; do
++ teststring=$teststring$teststring
++ done
++ SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
++ # If test is not a shell built-in, we'll probably end up computing a
++ # maximum length that is only half of the actual maximum length, but
++ # we can't tell.
++ while { test X`env echo "$teststring$teststring" 2>/dev/null` \
++ = "X$teststring$teststring"; } >/dev/null 2>&1 &&
++ test 17 != "$i" # 1/2 MB should be enough
++ do
++ i=`expr $i + 1`
++ teststring=$teststring$teststring
++ done
++ # Only check the string length outside the loop.
++ lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1`
++ teststring=
++ # Add a significant safety factor because C++ compilers can tack on
++ # massive amounts of additional arguments before passing them to the
++ # linker. It appears as though 1/2 is a usable value.
++ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
++ fi
++ ;;
++ esac
++])
++if test -n "$lt_cv_sys_max_cmd_len"; then
++ AC_MSG_RESULT($lt_cv_sys_max_cmd_len)
++else
++ AC_MSG_RESULT(none)
++fi
++max_cmd_len=$lt_cv_sys_max_cmd_len
++_LT_DECL([], [max_cmd_len], [0],
++ [What is the maximum length of a command?])
++])# LT_CMD_MAX_LEN
++
++# Old name:
++AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN])
++dnl aclocal-1.4 backwards compatibility:
++dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], [])
++
++
++# _LT_HEADER_DLFCN
++# ----------------
++m4_defun([_LT_HEADER_DLFCN],
++[AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl
++])# _LT_HEADER_DLFCN
++
++
++# _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE,
++# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING)
++# ----------------------------------------------------------------
++m4_defun([_LT_TRY_DLOPEN_SELF],
++[m4_require([_LT_HEADER_DLFCN])dnl
++if test yes = "$cross_compiling"; then :
++ [$4]
++else
++ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
++ lt_status=$lt_dlunknown
++ cat > conftest.$ac_ext <<_LT_EOF
++[#line $LINENO "configure"
++#include "confdefs.h"
++
++#if HAVE_DLFCN_H
++#include <dlfcn.h>
++#endif
++
++#include <stdio.h>
++
++#ifdef RTLD_GLOBAL
++# define LT_DLGLOBAL RTLD_GLOBAL
++#else
++# ifdef DL_GLOBAL
++# define LT_DLGLOBAL DL_GLOBAL
++# else
++# define LT_DLGLOBAL 0
++# endif
++#endif
++
++/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
++ find out it does not work in some platform. */
++#ifndef LT_DLLAZY_OR_NOW
++# ifdef RTLD_LAZY
++# define LT_DLLAZY_OR_NOW RTLD_LAZY
++# else
++# ifdef DL_LAZY
++# define LT_DLLAZY_OR_NOW DL_LAZY
++# else
++# ifdef RTLD_NOW
++# define LT_DLLAZY_OR_NOW RTLD_NOW
++# else
++# ifdef DL_NOW
++# define LT_DLLAZY_OR_NOW DL_NOW
++# else
++# define LT_DLLAZY_OR_NOW 0
++# endif
++# endif
++# endif
++# endif
++#endif
++
++/* When -fvisibility=hidden is used, assume the code has been annotated
++ correspondingly for the symbols needed. */
++#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))
++int fnord () __attribute__((visibility("default")));
++#endif
++
++int fnord () { return 42; }
++int main ()
++{
++ void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
++ int status = $lt_dlunknown;
++
++ if (self)
++ {
++ if (dlsym (self,"fnord")) status = $lt_dlno_uscore;
++ else
++ {
++ if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
++ else puts (dlerror ());
++ }
++ /* dlclose (self); */
++ }
++ else
++ puts (dlerror ());
++
++ return status;
++}]
++_LT_EOF
++ if AC_TRY_EVAL(ac_link) && test -s "conftest$ac_exeext" 2>/dev/null; then
++ (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null
++ lt_status=$?
++ case x$lt_status in
++ x$lt_dlno_uscore) $1 ;;
++ x$lt_dlneed_uscore) $2 ;;
++ x$lt_dlunknown|x*) $3 ;;
++ esac
++ else :
++ # compilation failed
++ $3
++ fi
++fi
++rm -fr conftest*
++])# _LT_TRY_DLOPEN_SELF
++
++
++# LT_SYS_DLOPEN_SELF
++# ------------------
++AC_DEFUN([LT_SYS_DLOPEN_SELF],
++[m4_require([_LT_HEADER_DLFCN])dnl
++if test yes != "$enable_dlopen"; then
++ enable_dlopen=unknown
++ enable_dlopen_self=unknown
++ enable_dlopen_self_static=unknown
++else
++ lt_cv_dlopen=no
++ lt_cv_dlopen_libs=
++
++ case $host_os in
++ beos*)
++ lt_cv_dlopen=load_add_on
++ lt_cv_dlopen_libs=
++ lt_cv_dlopen_self=yes
++ ;;
++
++ mingw* | pw32* | cegcc*)
++ lt_cv_dlopen=LoadLibrary
++ lt_cv_dlopen_libs=
++ ;;
++
++ cygwin*)
++ lt_cv_dlopen=dlopen
++ lt_cv_dlopen_libs=
++ ;;
++
++ darwin*)
++ # if libdl is installed we need to link against it
++ AC_CHECK_LIB([dl], [dlopen],
++ [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl],[
++ lt_cv_dlopen=dyld
++ lt_cv_dlopen_libs=
++ lt_cv_dlopen_self=yes
++ ])
++ ;;
++
++ tpf*)
++ # Don't try to run any link tests for TPF. We know it's impossible
++ # because TPF is a cross-compiler, and we know how we open DSOs.
++ lt_cv_dlopen=dlopen
++ lt_cv_dlopen_libs=
++ lt_cv_dlopen_self=no
++ ;;
++
++ *)
++ AC_CHECK_FUNC([shl_load],
++ [lt_cv_dlopen=shl_load],
++ [AC_CHECK_LIB([dld], [shl_load],
++ [lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld],
++ [AC_CHECK_FUNC([dlopen],
++ [lt_cv_dlopen=dlopen],
++ [AC_CHECK_LIB([dl], [dlopen],
++ [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl],
++ [AC_CHECK_LIB([svld], [dlopen],
++ [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld],
++ [AC_CHECK_LIB([dld], [dld_link],
++ [lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld])
++ ])
++ ])
++ ])
++ ])
++ ])
++ ;;
++ esac
++
++ if test no = "$lt_cv_dlopen"; then
++ enable_dlopen=no
++ else
++ enable_dlopen=yes
++ fi
++
++ case $lt_cv_dlopen in
++ dlopen)
++ save_CPPFLAGS=$CPPFLAGS
++ test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
++
++ save_LDFLAGS=$LDFLAGS
++ wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
++
++ save_LIBS=$LIBS
++ LIBS="$lt_cv_dlopen_libs $LIBS"
++
++ AC_CACHE_CHECK([whether a program can dlopen itself],
++ lt_cv_dlopen_self, [dnl
++ _LT_TRY_DLOPEN_SELF(
++ lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes,
++ lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross)
++ ])
++
++ if test yes = "$lt_cv_dlopen_self"; then
++ wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
++ AC_CACHE_CHECK([whether a statically linked program can dlopen itself],
++ lt_cv_dlopen_self_static, [dnl
++ _LT_TRY_DLOPEN_SELF(
++ lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes,
++ lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross)
++ ])
++ fi
++
++ CPPFLAGS=$save_CPPFLAGS
++ LDFLAGS=$save_LDFLAGS
++ LIBS=$save_LIBS
++ ;;
++ esac
++
++ case $lt_cv_dlopen_self in
++ yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
++ *) enable_dlopen_self=unknown ;;
++ esac
++
++ case $lt_cv_dlopen_self_static in
++ yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
++ *) enable_dlopen_self_static=unknown ;;
++ esac
++fi
++_LT_DECL([dlopen_support], [enable_dlopen], [0],
++ [Whether dlopen is supported])
++_LT_DECL([dlopen_self], [enable_dlopen_self], [0],
++ [Whether dlopen of programs is supported])
++_LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0],
++ [Whether dlopen of statically linked programs is supported])
++])# LT_SYS_DLOPEN_SELF
++
++# Old name:
++AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF])
++dnl aclocal-1.4 backwards compatibility:
++dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], [])
++
++
++# _LT_COMPILER_C_O([TAGNAME])
++# ---------------------------
++# Check to see if options -c and -o are simultaneously supported by compiler.
++# This macro does not hard code the compiler like AC_PROG_CC_C_O.
++m4_defun([_LT_COMPILER_C_O],
++[m4_require([_LT_DECL_SED])dnl
++m4_require([_LT_FILEUTILS_DEFAULTS])dnl
++m4_require([_LT_TAG_COMPILER])dnl
++AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext],
++ [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)],
++ [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no
++ $RM -r conftest 2>/dev/null
++ mkdir conftest
++ cd conftest
++ mkdir out
++ echo "$lt_simple_compile_test_code" > conftest.$ac_ext
++
++ lt_compiler_flag="-o out/conftest2.$ac_objext"
++ # Insert the option either (1) after the last *FLAGS variable, or
++ # (2) before a word containing "conftest.", or (3) at the end.
++ # Note that $ac_compile itself does not contain backslashes and begins
++ # with a dollar sign (not a hyphen), so the echo should work correctly.
++ lt_compile=`echo "$ac_compile" | $SED \
++ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
++ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
++ -e 's:$: $lt_compiler_flag:'`
++ (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
++ (eval "$lt_compile" 2>out/conftest.err)
++ ac_status=$?
++ cat out/conftest.err >&AS_MESSAGE_LOG_FD
++ echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
++ if (exit $ac_status) && test -s out/conftest2.$ac_objext
++ then
++ # The compiler can only warn and ignore the option if not recognized
++ # So say no if there are warnings
++ $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
++ $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
++ if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
++ _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
++ fi
++ fi
++ chmod u+w . 2>&AS_MESSAGE_LOG_FD
++ $RM conftest*
++ # SGI C++ compiler will create directory out/ii_files/ for
++ # template instantiation
++ test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
++ $RM out/* && rmdir out
++ cd ..
++ $RM -r conftest
++ $RM conftest*
++])
++_LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1],
++ [Does compiler simultaneously support -c and -o options?])
++])# _LT_COMPILER_C_O
++
++
++# _LT_COMPILER_FILE_LOCKS([TAGNAME])
++# ----------------------------------
++# Check to see if we can do hard links to lock some files if needed
++m4_defun([_LT_COMPILER_FILE_LOCKS],
++[m4_require([_LT_ENABLE_LOCK])dnl
++m4_require([_LT_FILEUTILS_DEFAULTS])dnl
++_LT_COMPILER_C_O([$1])
++
++hard_links=nottested
++if test no = "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" && test no != "$need_locks"; then
++ # do not overwrite the value of need_locks provided by the user
++ AC_MSG_CHECKING([if we can lock with hard links])
++ hard_links=yes
++ $RM conftest*
++ ln conftest.a conftest.b 2>/dev/null && hard_links=no
++ touch conftest.a
++ ln conftest.a conftest.b 2>&5 || hard_links=no
++ ln conftest.a conftest.b 2>/dev/null && hard_links=no
++ AC_MSG_RESULT([$hard_links])
++ if test no = "$hard_links"; then
++ AC_MSG_WARN(['$CC' does not support '-c -o', so 'make -j' may be unsafe])
++ need_locks=warn
++ fi
++else
++ need_locks=no
++fi
++_LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?])
++])# _LT_COMPILER_FILE_LOCKS
++
++
++# _LT_CHECK_OBJDIR
++# ----------------
++m4_defun([_LT_CHECK_OBJDIR],
++[AC_CACHE_CHECK([for objdir], [lt_cv_objdir],
++[rm -f .libs 2>/dev/null
++mkdir .libs 2>/dev/null
++if test -d .libs; then
++ lt_cv_objdir=.libs
++else
++ # MS-DOS does not allow filenames that begin with a dot.
++ lt_cv_objdir=_libs
++fi
++rmdir .libs 2>/dev/null])
++objdir=$lt_cv_objdir
++_LT_DECL([], [objdir], [0],
++ [The name of the directory that contains temporary libtool files])dnl
++m4_pattern_allow([LT_OBJDIR])dnl
++AC_DEFINE_UNQUOTED([LT_OBJDIR], "$lt_cv_objdir/",
++ [Define to the sub-directory where libtool stores uninstalled libraries.])
++])# _LT_CHECK_OBJDIR
++
++
++# _LT_LINKER_HARDCODE_LIBPATH([TAGNAME])
++# --------------------------------------
++# Check hardcoding attributes.
++m4_defun([_LT_LINKER_HARDCODE_LIBPATH],
++[AC_MSG_CHECKING([how to hardcode library paths into programs])
++_LT_TAGVAR(hardcode_action, $1)=
++if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" ||
++ test -n "$_LT_TAGVAR(runpath_var, $1)" ||
++ test yes = "$_LT_TAGVAR(hardcode_automatic, $1)"; then
++
++ # We can hardcode non-existent directories.
++ if test no != "$_LT_TAGVAR(hardcode_direct, $1)" &&
++ # If the only mechanism to avoid hardcoding is shlibpath_var, we
++ # have to relink, otherwise we might link with an installed library
++ # when we should be linking with a yet-to-be-installed one
++ ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" &&
++ test no != "$_LT_TAGVAR(hardcode_minus_L, $1)"; then
++ # Linking always hardcodes the temporary library directory.
++ _LT_TAGVAR(hardcode_action, $1)=relink
++ else
++ # We can link without hardcoding, and we can hardcode nonexisting dirs.
++ _LT_TAGVAR(hardcode_action, $1)=immediate
++ fi
++else
++ # We cannot hardcode anything, or else we can only hardcode existing
++ # directories.
++ _LT_TAGVAR(hardcode_action, $1)=unsupported
++fi
++AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)])
++
++if test relink = "$_LT_TAGVAR(hardcode_action, $1)" ||
++ test yes = "$_LT_TAGVAR(inherit_rpath, $1)"; then
++ # Fast installation is not supported
++ enable_fast_install=no
++elif test yes = "$shlibpath_overrides_runpath" ||
++ test no = "$enable_shared"; then
++ # Fast installation is not necessary
++ enable_fast_install=needless
++fi
++_LT_TAGDECL([], [hardcode_action], [0],
++ [How to hardcode a shared library path into an executable])
++])# _LT_LINKER_HARDCODE_LIBPATH
++
++
++# _LT_CMD_STRIPLIB
++# ----------------
++m4_defun([_LT_CMD_STRIPLIB],
++[m4_require([_LT_DECL_EGREP])
++striplib=
++old_striplib=
++AC_MSG_CHECKING([whether stripping libraries is possible])
++if test -z "$STRIP"; then
++ AC_MSG_RESULT([no])
++else
++ if $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then
++ old_striplib="$STRIP --strip-debug"
++ striplib="$STRIP --strip-unneeded"
++ AC_MSG_RESULT([yes])
++ else
++ case $host_os in
++ darwin*)
++ # FIXME - insert some real tests, host_os isn't really good enough
++ striplib="$STRIP -x"
++ old_striplib="$STRIP -S"
++ AC_MSG_RESULT([yes])
++ ;;
++ freebsd*)
++ if $STRIP -V 2>&1 | $GREP "elftoolchain" >/dev/null; then
++ old_striplib="$STRIP --strip-debug"
++ striplib="$STRIP --strip-unneeded"
++ AC_MSG_RESULT([yes])
++ else
++ AC_MSG_RESULT([no])
++ fi
++ ;;
++ *)
++ AC_MSG_RESULT([no])
++ ;;
++ esac
++ fi
++fi
++_LT_DECL([], [old_striplib], [1], [Commands to strip libraries])
++_LT_DECL([], [striplib], [1])
++])# _LT_CMD_STRIPLIB
++
++
++# _LT_PREPARE_MUNGE_PATH_LIST
++# ---------------------------
++# Make sure func_munge_path_list() is defined correctly.
++m4_defun([_LT_PREPARE_MUNGE_PATH_LIST],
++[[# func_munge_path_list VARIABLE PATH
++# -----------------------------------
++# VARIABLE is name of variable containing _space_ separated list of
++# directories to be munged by the contents of PATH, which is string
++# having a format:
++# "DIR[:DIR]:"
++# string "DIR[ DIR]" will be prepended to VARIABLE
++# ":DIR[:DIR]"
++# string "DIR[ DIR]" will be appended to VARIABLE
++# "DIRP[:DIRP]::[DIRA:]DIRA"
++# string "DIRP[ DIRP]" will be prepended to VARIABLE and string
++# "DIRA[ DIRA]" will be appended to VARIABLE
++# "DIR[:DIR]"
++# VARIABLE will be replaced by "DIR[ DIR]"
++func_munge_path_list ()
++{
++ case x@S|@2 in
++ x)
++ ;;
++ *:)
++ eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'` \@S|@@S|@1\"
++ ;;
++ x:*)
++ eval @S|@1=\"\@S|@@S|@1 `$ECHO @S|@2 | $SED 's/:/ /g'`\"
++ ;;
++ *::*)
++ eval @S|@1=\"\@S|@@S|@1\ `$ECHO @S|@2 | $SED -e 's/.*:://' -e 's/:/ /g'`\"
++ eval @S|@1=\"`$ECHO @S|@2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \@S|@@S|@1\"
++ ;;
++ *)
++ eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'`\"
++ ;;
++ esac
++}
++]])# _LT_PREPARE_PATH_LIST
++
++
++# _LT_SYS_DYNAMIC_LINKER([TAG])
++# -----------------------------
++# PORTME Fill in your ld.so characteristics
++m4_defun([_LT_SYS_DYNAMIC_LINKER],
++[AC_REQUIRE([AC_CANONICAL_HOST])dnl
++m4_require([_LT_DECL_EGREP])dnl
++m4_require([_LT_FILEUTILS_DEFAULTS])dnl
++m4_require([_LT_DECL_OBJDUMP])dnl
++m4_require([_LT_DECL_SED])dnl
++m4_require([_LT_CHECK_SHELL_FEATURES])dnl
++m4_require([_LT_PREPARE_MUNGE_PATH_LIST])dnl
++AC_MSG_CHECKING([dynamic linker characteristics])
++m4_if([$1],
++ [], [
++if test yes = "$GCC"; then
++ case $host_os in
++ darwin*) lt_awk_arg='/^libraries:/,/LR/' ;;
++ *) lt_awk_arg='/^libraries:/' ;;
++ esac
++ case $host_os in
++ mingw* | cegcc*) lt_sed_strip_eq='s|=\([[A-Za-z]]:\)|\1|g' ;;
++ *) lt_sed_strip_eq='s|=/|/|g' ;;
++ esac
++ lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq`
++ case $lt_search_path_spec in
++ *\;*)
++ # if the path contains ";" then we assume it to be the separator
++ # otherwise default to the standard path separator (i.e. ":") - it is
++ # assumed that no part of a normal pathname contains ";" but that should
++ # okay in the real world where ";" in dirpaths is itself problematic.
++ lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'`
++ ;;
++ *)
++ lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"`
++ ;;
++ esac
++ # Ok, now we have the path, separated by spaces, we can step through it
++ # and add multilib dir if necessary...
++ lt_tmp_lt_search_path_spec=
++ lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null`
++ # ...but if some path component already ends with the multilib dir we assume
++ # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer).
++ case "$lt_multi_os_dir; $lt_search_path_spec " in
++ "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*)
++ lt_multi_os_dir=
++ ;;
++ esac
++ for lt_sys_path in $lt_search_path_spec; do
++ if test -d "$lt_sys_path$lt_multi_os_dir"; then
++ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir"
++ elif test -n "$lt_multi_os_dir"; then
++ test -d "$lt_sys_path" && \
++ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path"
++ fi
++ done
++ lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk '
++BEGIN {RS = " "; FS = "/|\n";} {
++ lt_foo = "";
++ lt_count = 0;
++ for (lt_i = NF; lt_i > 0; lt_i--) {
++ if ($lt_i != "" && $lt_i != ".") {
++ if ($lt_i == "..") {
++ lt_count++;
++ } else {
++ if (lt_count == 0) {
++ lt_foo = "/" $lt_i lt_foo;
++ } else {
++ lt_count--;
++ }
++ }
++ }
++ }
++ if (lt_foo != "") { lt_freq[[lt_foo]]++; }
++ if (lt_freq[[lt_foo]] == 1) { print lt_foo; }
++}'`
++ # AWK program above erroneously prepends '/' to C:/dos/paths
++ # for these hosts.
++ case $host_os in
++ mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\
++ $SED 's|/\([[A-Za-z]]:\)|\1|g'` ;;
++ esac
++ sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP`
++else
++ sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
++fi])
++library_names_spec=
++libname_spec='lib$name'
++soname_spec=
++shrext_cmds=.so
++postinstall_cmds=
++postuninstall_cmds=
++finish_cmds=
++finish_eval=
++shlibpath_var=
++shlibpath_overrides_runpath=unknown
++version_type=none
++dynamic_linker="$host_os ld.so"
++sys_lib_dlsearch_path_spec="/lib /usr/lib"
++need_lib_prefix=unknown
++hardcode_into_libs=no
++
++# when you set need_version to no, make sure it does not cause -set_version
++# flags to be left without arguments
++need_version=unknown
++
++AC_ARG_VAR([LT_SYS_LIBRARY_PATH],
++[User-defined run-time library search path.])
++
++case $host_os in
++aix3*)
++ version_type=linux # correct to gnu/linux during the next big refactor
++ library_names_spec='$libname$release$shared_ext$versuffix $libname.a'
++ shlibpath_var=LIBPATH
++
++ # AIX 3 has no versioning support, so we append a major version to the name.
++ soname_spec='$libname$release$shared_ext$major'
++ ;;
++
++aix[[4-9]]*)
++ version_type=linux # correct to gnu/linux during the next big refactor
++ need_lib_prefix=no
++ need_version=no
++ hardcode_into_libs=yes
++ if test ia64 = "$host_cpu"; then
++ # AIX 5 supports IA64
++ library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext'
++ shlibpath_var=LD_LIBRARY_PATH
++ else
++ # With GCC up to 2.95.x, collect2 would create an import file
++ # for dependence libraries. The import file would start with
++ # the line '#! .'. This would cause the generated library to
++ # depend on '.', always an invalid library. This was fixed in
++ # development snapshots of GCC prior to 3.0.
++ case $host_os in
++ aix4 | aix4.[[01]] | aix4.[[01]].*)
++ if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
++ echo ' yes '
++ echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then
++ :
++ else
++ can_build_shared=no
++ fi
++ ;;
++ esac
++ # Using Import Files as archive members, it is possible to support
++ # filename-based versioning of shared library archives on AIX. While
++ # this would work for both with and without runtime linking, it will
++ # prevent static linking of such archives. So we do filename-based
++ # shared library versioning with .so extension only, which is used
++ # when both runtime linking and shared linking is enabled.
++ # Unfortunately, runtime linking may impact performance, so we do
++ # not want this to be the default eventually. Also, we use the
++ # versioned .so libs for executables only if there is the -brtl
++ # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only.
++ # To allow for filename-based versioning support, we need to create
++ # libNAME.so.V as an archive file, containing:
++ # *) an Import File, referring to the versioned filename of the
++ # archive as well as the shared archive member, telling the
++ # bitwidth (32 or 64) of that shared object, and providing the
++ # list of exported symbols of that shared object, eventually
++ # decorated with the 'weak' keyword
++ # *) the shared object with the F_LOADONLY flag set, to really avoid
++ # it being seen by the linker.
++ # At run time we better use the real file rather than another symlink,
++ # but for link time we create the symlink libNAME.so -> libNAME.so.V
++
++ case $with_aix_soname,$aix_use_runtimelinking in
++ # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct
++ # soname into executable. Probably we can add versioning support to
++ # collect2, so additional links can be useful in future.
++ aix,yes) # traditional libtool
++ dynamic_linker='AIX unversionable lib.so'
++ # If using run time linking (on AIX 4.2 or later) use lib<name>.so
++ # instead of lib<name>.a to let people know that these are not
++ # typical AIX shared libraries.
++ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++ ;;
++ aix,no) # traditional AIX only
++ dynamic_linker='AIX lib.a[(]lib.so.V[)]'
++ # We preserve .a as extension for shared libraries through AIX4.2
++ # and later when we are not doing run time linking.
++ library_names_spec='$libname$release.a $libname.a'
++ soname_spec='$libname$release$shared_ext$major'
++ ;;
++ svr4,*) # full svr4 only
++ dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)]"
++ library_names_spec='$libname$release$shared_ext$major $libname$shared_ext'
++ # We do not specify a path in Import Files, so LIBPATH fires.
++ shlibpath_overrides_runpath=yes
++ ;;
++ *,yes) # both, prefer svr4
++ dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)], lib.a[(]lib.so.V[)]"
++ library_names_spec='$libname$release$shared_ext$major $libname$shared_ext'
++ # unpreferred sharedlib libNAME.a needs extra handling
++ postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"'
++ postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"'
++ # We do not specify a path in Import Files, so LIBPATH fires.
++ shlibpath_overrides_runpath=yes
++ ;;
++ *,no) # both, prefer aix
++ dynamic_linker="AIX lib.a[(]lib.so.V[)], lib.so.V[(]$shared_archive_member_spec.o[)]"
++ library_names_spec='$libname$release.a $libname.a'
++ soname_spec='$libname$release$shared_ext$major'
++ # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling
++ postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)'
++ postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"'
++ ;;
++ esac
++ shlibpath_var=LIBPATH
++ fi
++ ;;
++
++amigaos*)
++ case $host_cpu in
++ powerpc)
++ # Since July 2007 AmigaOS4 officially supports .so libraries.
++ # When compiling the executable, add -use-dynld -Lsobjs: to the compileline.
++ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++ ;;
++ m68k)
++ library_names_spec='$libname.ixlibrary $libname.a'
++ # Create ${libname}_ixlibrary.a entries in /sys/libs.
++ finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
++ ;;
++ esac
++ ;;
++
++beos*)
++ library_names_spec='$libname$shared_ext'
++ dynamic_linker="$host_os ld.so"
++ shlibpath_var=LIBRARY_PATH
++ ;;
++
++bsdi[[45]]*)
++ version_type=linux # correct to gnu/linux during the next big refactor
++ need_version=no
++ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++ soname_spec='$libname$release$shared_ext$major'
++ finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
++ shlibpath_var=LD_LIBRARY_PATH
++ sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
++ sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
++ # the default ld.so.conf also contains /usr/contrib/lib and
++ # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
++ # libtool to hard-code these into programs
++ ;;
++
++cygwin* | mingw* | pw32* | cegcc*)
++ version_type=windows
++ shrext_cmds=.dll
++ need_version=no
++ need_lib_prefix=no
++
++ case $GCC,$cc_basename in
++ yes,*)
++ # gcc
++ library_names_spec='$libname.dll.a'
++ # DLL is installed to $(libdir)/../bin by postinstall_cmds
++ postinstall_cmds='base_file=`basename \$file`~
++ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~
++ dldir=$destdir/`dirname \$dlpath`~
++ test -d \$dldir || mkdir -p \$dldir~
++ $install_prog $dir/$dlname \$dldir/$dlname~
++ chmod a+x \$dldir/$dlname~
++ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
++ eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
++ fi'
++ postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
++ dlpath=$dir/\$dldll~
++ $RM \$dlpath'
++ shlibpath_overrides_runpath=yes
++
++ case $host_os in
++ cygwin*)
++ # Cygwin DLLs use 'cyg' prefix rather than 'lib'
++ soname_spec='`echo $libname | $SED -e 's/^lib/cyg/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext'
++m4_if([$1], [],[
++ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"])
++ ;;
++ mingw* | cegcc*)
++ # MinGW DLLs use traditional 'lib' prefix
++ soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext'
++ ;;
++ pw32*)
++ # pw32 DLLs use 'pw' prefix rather than 'lib'
++ library_names_spec='`echo $libname | $SED -e 's/^lib/pw/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext'
++ ;;
++ esac
++ dynamic_linker='Win32 ld.exe'
++ ;;
++
++ *,cl* | *,icl*)
++ # Native MSVC or ICC
++ libname_spec='$name'
++ soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext'
++ library_names_spec='$libname.dll.lib'
++
++ case $build_os in
++ mingw*)
++ sys_lib_search_path_spec=
++ lt_save_ifs=$IFS
++ IFS=';'
++ for lt_path in $LIB
++ do
++ IFS=$lt_save_ifs
++ # Let DOS variable expansion print the short 8.3 style file name.
++ lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"`
++ sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path"
++ done
++ IFS=$lt_save_ifs
++ # Convert to MSYS style.
++ sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'`
++ ;;
++ cygwin*)
++ # Convert to unix form, then to dos form, then back to unix form
++ # but this time dos style (no spaces!) so that the unix form looks
++ # like /cygdrive/c/PROGRA~1:/cygdr...
++ sys_lib_search_path_spec=`cygpath --path --unix "$LIB"`
++ sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null`
++ sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
++ ;;
++ *)
++ sys_lib_search_path_spec=$LIB
++ if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then
++ # It is most probably a Windows format PATH.
++ sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
++ else
++ sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
++ fi
++ # FIXME: find the short name or the path components, as spaces are
++ # common. (e.g. "Program Files" -> "PROGRA~1")
++ ;;
++ esac
++
++ # DLL is installed to $(libdir)/../bin by postinstall_cmds
++ postinstall_cmds='base_file=`basename \$file`~
++ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~
++ dldir=$destdir/`dirname \$dlpath`~
++ test -d \$dldir || mkdir -p \$dldir~
++ $install_prog $dir/$dlname \$dldir/$dlname'
++ postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
++ dlpath=$dir/\$dldll~
++ $RM \$dlpath'
++ shlibpath_overrides_runpath=yes
++ dynamic_linker='Win32 link.exe'
++ ;;
++
++ *)
++ # Assume MSVC and ICC wrapper
++ library_names_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext $libname.lib'
++ dynamic_linker='Win32 ld.exe'
++ ;;
++ esac
++ # FIXME: first we should search . and the directory the executable is in
++ shlibpath_var=PATH
++ ;;
++
++darwin* | rhapsody*)
++ dynamic_linker="$host_os dyld"
++ version_type=darwin
++ need_lib_prefix=no
++ need_version=no
++ library_names_spec='$libname$release$major$shared_ext $libname$shared_ext'
++ soname_spec='$libname$release$major$shared_ext'
++ shlibpath_overrides_runpath=yes
++ shlibpath_var=DYLD_LIBRARY_PATH
++ shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
++m4_if([$1], [],[
++ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"])
++ sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
++ ;;
++
++dgux*)
++ version_type=linux # correct to gnu/linux during the next big refactor
++ need_lib_prefix=no
++ need_version=no
++ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++ soname_spec='$libname$release$shared_ext$major'
++ shlibpath_var=LD_LIBRARY_PATH
++ ;;
++
++freebsd* | dragonfly* | midnightbsd*)
++ # DragonFly does not have aout. When/if they implement a new
++ # versioning mechanism, adjust this.
++ if test -x /usr/bin/objformat; then
++ objformat=`/usr/bin/objformat`
++ else
++ case $host_os in
++ freebsd[[23]].*) objformat=aout ;;
++ *) objformat=elf ;;
++ esac
++ fi
++ version_type=freebsd-$objformat
++ case $version_type in
++ freebsd-elf*)
++ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++ soname_spec='$libname$release$shared_ext$major'
++ need_version=no
++ need_lib_prefix=no
++ ;;
++ freebsd-*)
++ library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
++ need_version=yes
++ ;;
++ esac
++ shlibpath_var=LD_LIBRARY_PATH
++ case $host_os in
++ freebsd2.*)
++ shlibpath_overrides_runpath=yes
++ ;;
++ freebsd3.[[01]]* | freebsdelf3.[[01]]*)
++ shlibpath_overrides_runpath=yes
++ hardcode_into_libs=yes
++ ;;
++ freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \
++ freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1)
++ shlibpath_overrides_runpath=no
++ hardcode_into_libs=yes
++ ;;
++ *) # from 4.6 on, and DragonFly
++ shlibpath_overrides_runpath=yes
++ hardcode_into_libs=yes
++ ;;
++ esac
++ ;;
++
++haiku*)
++ version_type=linux # correct to gnu/linux during the next big refactor
++ need_lib_prefix=no
++ need_version=no
++ dynamic_linker="$host_os runtime_loader"
++ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++ soname_spec='$libname$release$shared_ext$major'
++ shlibpath_var=LIBRARY_PATH
++ shlibpath_overrides_runpath=no
++ sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib'
++ hardcode_into_libs=yes
++ ;;
++
++hpux9* | hpux10* | hpux11*)
++ # Give a soname corresponding to the major version so that dld.sl refuses to
++ # link against other versions.
++ version_type=sunos
++ need_lib_prefix=no
++ need_version=no
++ case $host_cpu in
++ ia64*)
++ shrext_cmds='.so'
++ hardcode_into_libs=yes
++ dynamic_linker="$host_os dld.so"
++ shlibpath_var=LD_LIBRARY_PATH
++ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
++ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++ soname_spec='$libname$release$shared_ext$major'
++ if test 32 = "$HPUX_IA64_MODE"; then
++ sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
++ sys_lib_dlsearch_path_spec=/usr/lib/hpux32
++ else
++ sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
++ sys_lib_dlsearch_path_spec=/usr/lib/hpux64
++ fi
++ ;;
++ hppa*64*)
++ shrext_cmds='.sl'
++ hardcode_into_libs=yes
++ dynamic_linker="$host_os dld.sl"
++ shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
++ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
++ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++ soname_spec='$libname$release$shared_ext$major'
++ sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
++ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
++ ;;
++ *)
++ shrext_cmds='.sl'
++ dynamic_linker="$host_os dld.sl"
++ shlibpath_var=SHLIB_PATH
++ shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
++ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++ soname_spec='$libname$release$shared_ext$major'
++ ;;
++ esac
++ # HP-UX runs *really* slowly unless shared libraries are mode 555, ...
++ postinstall_cmds='chmod 555 $lib'
++ # or fails outright, so override atomically:
++ install_override_mode=555
++ ;;
++
++interix[[3-9]]*)
++ version_type=linux # correct to gnu/linux during the next big refactor
++ need_lib_prefix=no
++ need_version=no
++ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++ soname_spec='$libname$release$shared_ext$major'
++ dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
++ shlibpath_var=LD_LIBRARY_PATH
++ shlibpath_overrides_runpath=no
++ hardcode_into_libs=yes
++ ;;
++
++irix5* | irix6* | nonstopux*)
++ case $host_os in
++ nonstopux*) version_type=nonstopux ;;
++ *)
++ if test yes = "$lt_cv_prog_gnu_ld"; then
++ version_type=linux # correct to gnu/linux during the next big refactor
++ else
++ version_type=irix
++ fi ;;
++ esac
++ need_lib_prefix=no
++ need_version=no
++ soname_spec='$libname$release$shared_ext$major'
++ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext'
++ case $host_os in
++ irix5* | nonstopux*)
++ libsuff= shlibsuff=
++ ;;
++ *)
++ case $LD in # libtool.m4 will add one of these switches to LD
++ *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
++ libsuff= shlibsuff= libmagic=32-bit;;
++ *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
++ libsuff=32 shlibsuff=N32 libmagic=N32;;
++ *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
++ libsuff=64 shlibsuff=64 libmagic=64-bit;;
++ *) libsuff= shlibsuff= libmagic=never-match;;
++ esac
++ ;;
++ esac
++ shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
++ shlibpath_overrides_runpath=no
++ sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff"
++ sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff"
++ hardcode_into_libs=yes
++ ;;
++
++# No shared lib support for Linux oldld, aout, or coff.
++linux*oldld* | linux*aout* | linux*coff*)
++ dynamic_linker=no
++ ;;
++
++linux*android*)
++ version_type=none # Android doesn't support versioned libraries.
++ need_lib_prefix=no
++ need_version=no
++ library_names_spec='$libname$release$shared_ext'
++ soname_spec='$libname$release$shared_ext'
++ finish_cmds=
++ shlibpath_var=LD_LIBRARY_PATH
++ shlibpath_overrides_runpath=yes
++
++ # This implies no fast_install, which is unacceptable.
++ # Some rework will be needed to allow for fast_install
++ # before this can be enabled.
++ hardcode_into_libs=yes
++
++ dynamic_linker='Android linker'
++ # Don't embed -rpath directories since the linker doesn't support them.
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
++ ;;
++
++# This must be glibc/ELF.
++linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
++ version_type=linux # correct to gnu/linux during the next big refactor
++ need_lib_prefix=no
++ need_version=no
++ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++ soname_spec='$libname$release$shared_ext$major'
++ finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
++ shlibpath_var=LD_LIBRARY_PATH
++ shlibpath_overrides_runpath=no
++
++ # Some binutils ld are patched to set DT_RUNPATH
++ AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath],
++ [lt_cv_shlibpath_overrides_runpath=no
++ save_LDFLAGS=$LDFLAGS
++ save_libdir=$libdir
++ eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \
++ LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\""
++ AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])],
++ [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null],
++ [lt_cv_shlibpath_overrides_runpath=yes])])
++ LDFLAGS=$save_LDFLAGS
++ libdir=$save_libdir
++ ])
++ shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath
++
++ # This implies no fast_install, which is unacceptable.
++ # Some rework will be needed to allow for fast_install
++ # before this can be enabled.
++ hardcode_into_libs=yes
++
++ # Ideally, we could use ldconfig to report *all* directores which are
++ # searched for libraries, however this is still not possible. Aside from not
++ # being certain /sbin/ldconfig is available, command
++ # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64,
++ # even though it is searched at run-time. Try to do the best guess by
++ # appending ld.so.conf contents (and includes) to the search path.
++ if test -f /etc/ld.so.conf; then
++ lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '`
++ sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
++ fi
++
++ # We used to test for /lib/ld.so.1 and disable shared libraries on
++ # powerpc, because MkLinux only supported shared libraries with the
++ # GNU dynamic linker. Since this was broken with cross compilers,
++ # most powerpc-linux boxes support dynamic linking these days and
++ # people can always --disable-shared, the test was removed, and we
++ # assume the GNU/Linux dynamic linker is in use.
++ dynamic_linker='GNU/Linux ld.so'
++ ;;
++
++netbsd*)
++ version_type=sunos
++ need_lib_prefix=no
++ need_version=no
++ if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
++ library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
++ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
++ dynamic_linker='NetBSD (a.out) ld.so'
++ else
++ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++ soname_spec='$libname$release$shared_ext$major'
++ dynamic_linker='NetBSD ld.elf_so'
++ fi
++ shlibpath_var=LD_LIBRARY_PATH
++ shlibpath_overrides_runpath=yes
++ hardcode_into_libs=yes
++ ;;
++
++newsos6)
++ version_type=linux # correct to gnu/linux during the next big refactor
++ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++ shlibpath_var=LD_LIBRARY_PATH
++ shlibpath_overrides_runpath=yes
++ ;;
++
++*nto* | *qnx*)
++ version_type=qnx
++ need_lib_prefix=no
++ need_version=no
++ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++ soname_spec='$libname$release$shared_ext$major'
++ shlibpath_var=LD_LIBRARY_PATH
++ shlibpath_overrides_runpath=no
++ hardcode_into_libs=yes
++ dynamic_linker='ldqnx.so'
++ ;;
++
++openbsd* | bitrig*)
++ version_type=sunos
++ sys_lib_dlsearch_path_spec=/usr/lib
++ need_lib_prefix=no
++ if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
++ need_version=no
++ else
++ need_version=yes
++ fi
++ library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
++ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
++ shlibpath_var=LD_LIBRARY_PATH
++ shlibpath_overrides_runpath=yes
++ ;;
++
++os2*)
++ libname_spec='$name'
++ version_type=windows
++ shrext_cmds=.dll
++ need_version=no
++ need_lib_prefix=no
++ # OS/2 can only load a DLL with a base name of 8 characters or less.
++ soname_spec='`test -n "$os2dllname" && libname="$os2dllname";
++ v=$($ECHO $release$versuffix | tr -d .-);
++ n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _);
++ $ECHO $n$v`$shared_ext'
++ library_names_spec='${libname}_dll.$libext'
++ dynamic_linker='OS/2 ld.exe'
++ shlibpath_var=BEGINLIBPATH
++ sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
++ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
++ postinstall_cmds='base_file=`basename \$file`~
++ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~
++ dldir=$destdir/`dirname \$dlpath`~
++ test -d \$dldir || mkdir -p \$dldir~
++ $install_prog $dir/$dlname \$dldir/$dlname~
++ chmod a+x \$dldir/$dlname~
++ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
++ eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
++ fi'
++ postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~
++ dlpath=$dir/\$dldll~
++ $RM \$dlpath'
++ ;;
++
++osf3* | osf4* | osf5*)
++ version_type=osf
++ need_lib_prefix=no
++ need_version=no
++ soname_spec='$libname$release$shared_ext$major'
++ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++ shlibpath_var=LD_LIBRARY_PATH
++ sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
++ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
++ ;;
++
++rdos*)
++ dynamic_linker=no
++ ;;
++
++solaris*)
++ version_type=linux # correct to gnu/linux during the next big refactor
++ need_lib_prefix=no
++ need_version=no
++ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++ soname_spec='$libname$release$shared_ext$major'
++ shlibpath_var=LD_LIBRARY_PATH
++ shlibpath_overrides_runpath=yes
++ hardcode_into_libs=yes
++ # ldd complains unless libraries are executable
++ postinstall_cmds='chmod +x $lib'
++ ;;
++
++sunos4*)
++ version_type=sunos
++ library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
++ finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
++ shlibpath_var=LD_LIBRARY_PATH
++ shlibpath_overrides_runpath=yes
++ if test yes = "$with_gnu_ld"; then
++ need_lib_prefix=no
++ fi
++ need_version=yes
++ ;;
++
++sysv4 | sysv4.3*)
++ version_type=linux # correct to gnu/linux during the next big refactor
++ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++ soname_spec='$libname$release$shared_ext$major'
++ shlibpath_var=LD_LIBRARY_PATH
++ case $host_vendor in
++ sni)
++ shlibpath_overrides_runpath=no
++ need_lib_prefix=no
++ runpath_var=LD_RUN_PATH
++ ;;
++ siemens)
++ need_lib_prefix=no
++ ;;
++ motorola)
++ need_lib_prefix=no
++ need_version=no
++ shlibpath_overrides_runpath=no
++ sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
++ ;;
++ esac
++ ;;
++
++sysv4*MP*)
++ if test -d /usr/nec; then
++ version_type=linux # correct to gnu/linux during the next big refactor
++ library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext'
++ soname_spec='$libname$shared_ext.$major'
++ shlibpath_var=LD_LIBRARY_PATH
++ fi
++ ;;
++
++sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
++ version_type=sco
++ need_lib_prefix=no
++ need_version=no
++ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext'
++ soname_spec='$libname$release$shared_ext$major'
++ shlibpath_var=LD_LIBRARY_PATH
++ shlibpath_overrides_runpath=yes
++ hardcode_into_libs=yes
++ if test yes = "$with_gnu_ld"; then
++ sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
++ else
++ sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
++ case $host_os in
++ sco3.2v5*)
++ sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
++ ;;
++ esac
++ fi
++ sys_lib_dlsearch_path_spec='/usr/lib'
++ ;;
++
++tpf*)
++ # TPF is a cross-target only. Preferred cross-host = GNU/Linux.
++ version_type=linux # correct to gnu/linux during the next big refactor
++ need_lib_prefix=no
++ need_version=no
++ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++ shlibpath_var=LD_LIBRARY_PATH
++ shlibpath_overrides_runpath=no
++ hardcode_into_libs=yes
++ ;;
++
++uts4*)
++ version_type=linux # correct to gnu/linux during the next big refactor
++ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++ soname_spec='$libname$release$shared_ext$major'
++ shlibpath_var=LD_LIBRARY_PATH
++ ;;
++
++*)
++ dynamic_linker=no
++ ;;
++esac
++AC_MSG_RESULT([$dynamic_linker])
++test no = "$dynamic_linker" && can_build_shared=no
++
++variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
++if test yes = "$GCC"; then
++ variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
++fi
++
++if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then
++ sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec
++fi
++
++if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then
++ sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec
++fi
++
++# remember unaugmented sys_lib_dlsearch_path content for libtool script decls...
++configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec
++
++# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code
++func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH"
++
++# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool
++configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH
++
++_LT_DECL([], [variables_saved_for_relink], [1],
++ [Variables whose values should be saved in libtool wrapper scripts and
++ restored at link time])
++_LT_DECL([], [need_lib_prefix], [0],
++ [Do we need the "lib" prefix for modules?])
++_LT_DECL([], [need_version], [0], [Do we need a version for libraries?])
++_LT_DECL([], [version_type], [0], [Library versioning type])
++_LT_DECL([], [runpath_var], [0], [Shared library runtime path variable])
++_LT_DECL([], [shlibpath_var], [0],[Shared library path variable])
++_LT_DECL([], [shlibpath_overrides_runpath], [0],
++ [Is shlibpath searched before the hard-coded library search path?])
++_LT_DECL([], [libname_spec], [1], [Format of library name prefix])
++_LT_DECL([], [library_names_spec], [1],
++ [[List of archive names. First name is the real one, the rest are links.
++ The last name is the one that the linker finds with -lNAME]])
++_LT_DECL([], [soname_spec], [1],
++ [[The coded name of the library, if different from the real name]])
++_LT_DECL([], [install_override_mode], [1],
++ [Permission mode override for installation of shared libraries])
++_LT_DECL([], [postinstall_cmds], [2],
++ [Command to use after installation of a shared archive])
++_LT_DECL([], [postuninstall_cmds], [2],
++ [Command to use after uninstallation of a shared archive])
++_LT_DECL([], [finish_cmds], [2],
++ [Commands used to finish a libtool library installation in a directory])
++_LT_DECL([], [finish_eval], [1],
++ [[As "finish_cmds", except a single script fragment to be evaled but
++ not shown]])
++_LT_DECL([], [hardcode_into_libs], [0],
++ [Whether we should hardcode library paths into libraries])
++_LT_DECL([], [sys_lib_search_path_spec], [2],
++ [Compile-time system search path for libraries])
++_LT_DECL([sys_lib_dlsearch_path_spec], [configure_time_dlsearch_path], [2],
++ [Detected run-time system search path for libraries])
++_LT_DECL([], [configure_time_lt_sys_library_path], [2],
++ [Explicit LT_SYS_LIBRARY_PATH set during ./configure time])
++])# _LT_SYS_DYNAMIC_LINKER
++
++
++# _LT_PATH_TOOL_PREFIX(TOOL)
++# --------------------------
++# find a file program that can recognize shared library
++AC_DEFUN([_LT_PATH_TOOL_PREFIX],
++[m4_require([_LT_DECL_EGREP])dnl
++AC_MSG_CHECKING([for $1])
++AC_CACHE_VAL(lt_cv_path_MAGIC_CMD,
++[case $MAGIC_CMD in
++[[\\/*] | ?:[\\/]*])
++ lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path.
++ ;;
++*)
++ lt_save_MAGIC_CMD=$MAGIC_CMD
++ lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
++dnl $ac_dummy forces splitting on constant user-supplied paths.
++dnl POSIX.2 word splitting is done only on the output of word expansions,
++dnl not every word. This closes a longstanding sh security hole.
++ ac_dummy="m4_if([$2], , $PATH, [$2])"
++ for ac_dir in $ac_dummy; do
++ IFS=$lt_save_ifs
++ test -z "$ac_dir" && ac_dir=.
++ if test -f "$ac_dir/$1"; then
++ lt_cv_path_MAGIC_CMD=$ac_dir/"$1"
++ if test -n "$file_magic_test_file"; then
++ case $deplibs_check_method in
++ "file_magic "*)
++ file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
++ MAGIC_CMD=$lt_cv_path_MAGIC_CMD
++ if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
++ $EGREP "$file_magic_regex" > /dev/null; then
++ :
++ else
++ cat <<_LT_EOF 1>&2
++
++*** Warning: the command libtool uses to detect shared libraries,
++*** $file_magic_cmd, produces output that libtool cannot recognize.
++*** The result is that libtool may fail to recognize shared libraries
++*** as such. This will affect the creation of libtool libraries that
++*** depend on shared libraries, but programs linked with such libtool
++*** libraries will work regardless of this problem. Nevertheless, you
++*** may want to report the problem to your system manager and/or to
++*** bug-libtool@gnu.org
++
++_LT_EOF
++ fi ;;
++ esac
++ fi
++ break
++ fi
++ done
++ IFS=$lt_save_ifs
++ MAGIC_CMD=$lt_save_MAGIC_CMD
++ ;;
++esac])
++MAGIC_CMD=$lt_cv_path_MAGIC_CMD
++if test -n "$MAGIC_CMD"; then
++ AC_MSG_RESULT($MAGIC_CMD)
++else
++ AC_MSG_RESULT(no)
++fi
++_LT_DECL([], [MAGIC_CMD], [0],
++ [Used to examine libraries when file_magic_cmd begins with "file"])dnl
++])# _LT_PATH_TOOL_PREFIX
++
++# Old name:
++AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX])
++dnl aclocal-1.4 backwards compatibility:
++dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], [])
++
++
++# _LT_PATH_MAGIC
++# --------------
++# find a file program that can recognize a shared library
++m4_defun([_LT_PATH_MAGIC],
++[_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH)
++if test -z "$lt_cv_path_MAGIC_CMD"; then
++ if test -n "$ac_tool_prefix"; then
++ _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH)
++ else
++ MAGIC_CMD=:
++ fi
++fi
++])# _LT_PATH_MAGIC
++
++
++# LT_PATH_LD
++# ----------
++# find the pathname to the GNU or non-GNU linker
++AC_DEFUN([LT_PATH_LD],
++[AC_REQUIRE([AC_PROG_CC])dnl
++AC_REQUIRE([AC_CANONICAL_HOST])dnl
++AC_REQUIRE([AC_CANONICAL_BUILD])dnl
++m4_require([_LT_DECL_SED])dnl
++m4_require([_LT_DECL_EGREP])dnl
++m4_require([_LT_PROG_ECHO_BACKSLASH])dnl
++
++AC_ARG_WITH([gnu-ld],
++ [AS_HELP_STRING([--with-gnu-ld],
++ [assume the C compiler uses GNU ld @<:@default=no@:>@])],
++ [test no = "$withval" || with_gnu_ld=yes],
++ [with_gnu_ld=no])dnl
++
++ac_prog=ld
++if test yes = "$GCC"; then
++ # Check if gcc -print-prog-name=ld gives a path.
++ AC_MSG_CHECKING([for ld used by $CC])
++ case $host in
++ *-*-mingw*)
++ # gcc leaves a trailing carriage return, which upsets mingw
++ ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
++ *)
++ ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
++ esac
++ case $ac_prog in
++ # Accept absolute paths.
++ [[\\/]]* | ?:[[\\/]]*)
++ re_direlt='/[[^/]][[^/]]*/\.\./'
++ # Canonicalize the pathname of ld
++ ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'`
++ while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do
++ ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"`
++ done
++ test -z "$LD" && LD=$ac_prog
++ ;;
++ "")
++ # If it fails, then pretend we aren't using GCC.
++ ac_prog=ld
++ ;;
++ *)
++ # If it is relative, then search for the first ld in PATH.
++ with_gnu_ld=unknown
++ ;;
++ esac
++elif test yes = "$with_gnu_ld"; then
++ AC_MSG_CHECKING([for GNU ld])
++else
++ AC_MSG_CHECKING([for non-GNU ld])
++fi
++AC_CACHE_VAL(lt_cv_path_LD,
++[if test -z "$LD"; then
++ lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
++ for ac_dir in $PATH; do
++ IFS=$lt_save_ifs
++ test -z "$ac_dir" && ac_dir=.
++ if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
++ lt_cv_path_LD=$ac_dir/$ac_prog
++ # Check to see if the program is GNU ld. I'd rather use --version,
++ # but apparently some variants of GNU ld only accept -v.
++ # Break only if it was the GNU/non-GNU ld that we prefer.
++ case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
++ *GNU* | *'with BFD'*)
++ test no != "$with_gnu_ld" && break
++ ;;
++ *)
++ test yes != "$with_gnu_ld" && break
++ ;;
++ esac
++ fi
++ done
++ IFS=$lt_save_ifs
++else
++ lt_cv_path_LD=$LD # Let the user override the test with a path.
++fi])
++LD=$lt_cv_path_LD
++if test -n "$LD"; then
++ AC_MSG_RESULT($LD)
++else
++ AC_MSG_RESULT(no)
++fi
++test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
++_LT_PATH_LD_GNU
++AC_SUBST([LD])
++
++_LT_TAGDECL([], [LD], [1], [The linker used to build libraries])
++])# LT_PATH_LD
++
++# Old names:
++AU_ALIAS([AM_PROG_LD], [LT_PATH_LD])
++AU_ALIAS([AC_PROG_LD], [LT_PATH_LD])
++dnl aclocal-1.4 backwards compatibility:
++dnl AC_DEFUN([AM_PROG_LD], [])
++dnl AC_DEFUN([AC_PROG_LD], [])
++
++
++# _LT_PATH_LD_GNU
++#- --------------
++m4_defun([_LT_PATH_LD_GNU],
++[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], lt_cv_prog_gnu_ld,
++[# I'd rather use --version here, but apparently some GNU lds only accept -v.
++case `$LD -v 2>&1 </dev/null` in
++*GNU* | *'with BFD'*)
++ lt_cv_prog_gnu_ld=yes
++ ;;
++*)
++ lt_cv_prog_gnu_ld=no
++ ;;
++esac])
++with_gnu_ld=$lt_cv_prog_gnu_ld
++])# _LT_PATH_LD_GNU
++
++
++# _LT_CMD_RELOAD
++# --------------
++# find reload flag for linker
++# -- PORTME Some linkers may need a different reload flag.
++m4_defun([_LT_CMD_RELOAD],
++[AC_CACHE_CHECK([for $LD option to reload object files],
++ lt_cv_ld_reload_flag,
++ [lt_cv_ld_reload_flag='-r'])
++reload_flag=$lt_cv_ld_reload_flag
++case $reload_flag in
++"" | " "*) ;;
++*) reload_flag=" $reload_flag" ;;
++esac
++reload_cmds='$LD$reload_flag -o $output$reload_objs'
++case $host_os in
++ cygwin* | mingw* | pw32* | cegcc*)
++ if test yes != "$GCC"; then
++ reload_cmds=false
++ fi
++ ;;
++ darwin*)
++ if test yes = "$GCC"; then
++ reload_cmds='$LTCC $LTCFLAGS -nostdlib $wl-r -o $output$reload_objs'
++ else
++ reload_cmds='$LD$reload_flag -o $output$reload_objs'
++ fi
++ ;;
++esac
++_LT_TAGDECL([], [reload_flag], [1], [How to create reloadable object files])dnl
++_LT_TAGDECL([], [reload_cmds], [2])dnl
++])# _LT_CMD_RELOAD
++
++
++# _LT_PATH_DD
++# -----------
++# find a working dd
++m4_defun([_LT_PATH_DD],
++[AC_CACHE_CHECK([for a working dd], [ac_cv_path_lt_DD],
++[printf 0123456789abcdef0123456789abcdef >conftest.i
++cat conftest.i conftest.i >conftest2.i
++: ${lt_DD:=$DD}
++AC_PATH_PROGS_FEATURE_CHECK([lt_DD], [dd],
++[if "$ac_path_lt_DD" bs=32 count=1 <conftest2.i >conftest.out 2>/dev/null; then
++ cmp -s conftest.i conftest.out \
++ && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=:
++fi])
++rm -f conftest.i conftest2.i conftest.out])
++])# _LT_PATH_DD
++
++
++# _LT_CMD_TRUNCATE
++# ----------------
++# find command to truncate a binary pipe
++m4_defun([_LT_CMD_TRUNCATE],
++[m4_require([_LT_PATH_DD])
++AC_CACHE_CHECK([how to truncate binary pipes], [lt_cv_truncate_bin],
++[printf 0123456789abcdef0123456789abcdef >conftest.i
++cat conftest.i conftest.i >conftest2.i
++lt_cv_truncate_bin=
++if "$ac_cv_path_lt_DD" bs=32 count=1 <conftest2.i >conftest.out 2>/dev/null; then
++ cmp -s conftest.i conftest.out \
++ && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1"
++fi
++rm -f conftest.i conftest2.i conftest.out
++test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q"])
++_LT_DECL([lt_truncate_bin], [lt_cv_truncate_bin], [1],
++ [Command to truncate a binary pipe])
++])# _LT_CMD_TRUNCATE
++
++
++# _LT_CHECK_MAGIC_METHOD
++# ----------------------
++# how to check for library dependencies
++# -- PORTME fill in with the dynamic library characteristics
++m4_defun([_LT_CHECK_MAGIC_METHOD],
++[m4_require([_LT_DECL_EGREP])
++m4_require([_LT_DECL_OBJDUMP])
++AC_CACHE_CHECK([how to recognize dependent libraries],
++lt_cv_deplibs_check_method,
++[lt_cv_file_magic_cmd='$MAGIC_CMD'
++lt_cv_file_magic_test_file=
++lt_cv_deplibs_check_method='unknown'
++# Need to set the preceding variable on all platforms that support
++# interlibrary dependencies.
++# 'none' -- dependencies not supported.
++# 'unknown' -- same as none, but documents that we really don't know.
++# 'pass_all' -- all dependencies passed with no checks.
++# 'test_compile' -- check by making test program.
++# 'file_magic [[regex]]' -- check by looking for files in library path
++# that responds to the $file_magic_cmd with a given extended regex.
++# If you have 'file' or equivalent on your system and you're not sure
++# whether 'pass_all' will *always* work, you probably want this one.
++
++case $host_os in
++aix[[4-9]]*)
++ lt_cv_deplibs_check_method=pass_all
++ ;;
++
++beos*)
++ lt_cv_deplibs_check_method=pass_all
++ ;;
++
++bsdi[[45]]*)
++ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)'
++ lt_cv_file_magic_cmd='$FILECMD -L'
++ lt_cv_file_magic_test_file=/shlib/libc.so
++ ;;
++
++cygwin*)
++ # func_win32_libid is a shell function defined in ltmain.sh
++ lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
++ lt_cv_file_magic_cmd='func_win32_libid'
++ ;;
++
++mingw* | pw32*)
++ # Base MSYS/MinGW do not provide the 'file' command needed by
++ # func_win32_libid shell function, so use a weaker test based on 'objdump',
++ # unless we find 'file', for example because we are cross-compiling.
++ if ( file / ) >/dev/null 2>&1; then
++ lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
++ lt_cv_file_magic_cmd='func_win32_libid'
++ else
++ # Keep this pattern in sync with the one in func_win32_libid.
++ lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)'
++ lt_cv_file_magic_cmd='$OBJDUMP -f'
++ fi
++ ;;
++
++cegcc*)
++ # use the weaker test based on 'objdump'. See mingw*.
++ lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?'
++ lt_cv_file_magic_cmd='$OBJDUMP -f'
++ ;;
++
++darwin* | rhapsody*)
++ lt_cv_deplibs_check_method=pass_all
++ ;;
++
++freebsd* | dragonfly* | midnightbsd*)
++ if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
++ case $host_cpu in
++ i*86 )
++ # Not sure whether the presence of OpenBSD here was a mistake.
++ # Let's accept both of them until this is cleared up.
++ lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library'
++ lt_cv_file_magic_cmd=$FILECMD
++ lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
++ ;;
++ esac
++ else
++ lt_cv_deplibs_check_method=pass_all
++ fi
++ ;;
++
++haiku*)
++ lt_cv_deplibs_check_method=pass_all
++ ;;
++
++hpux10.20* | hpux11*)
++ lt_cv_file_magic_cmd=$FILECMD
++ case $host_cpu in
++ ia64*)
++ lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64'
++ lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
++ ;;
++ hppa*64*)
++ [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]']
++ lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
++ ;;
++ *)
++ lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library'
++ lt_cv_file_magic_test_file=/usr/lib/libc.sl
++ ;;
++ esac
++ ;;
++
++interix[[3-9]]*)
++ # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here
++ lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$'
++ ;;
++
++irix5* | irix6* | nonstopux*)
++ case $LD in
++ *-32|*"-32 ") libmagic=32-bit;;
++ *-n32|*"-n32 ") libmagic=N32;;
++ *-64|*"-64 ") libmagic=64-bit;;
++ *) libmagic=never-match;;
++ esac
++ lt_cv_deplibs_check_method=pass_all
++ ;;
++
++# This must be glibc/ELF.
++linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
++ lt_cv_deplibs_check_method=pass_all
++ ;;
++
++netbsd*)
++ if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
++ lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
++ else
++ lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$'
++ fi
++ ;;
++
++newos6*)
++ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)'
++ lt_cv_file_magic_cmd=$FILECMD
++ lt_cv_file_magic_test_file=/usr/lib/libnls.so
++ ;;
++
++*nto* | *qnx*)
++ lt_cv_deplibs_check_method=pass_all
++ ;;
++
++openbsd* | bitrig*)
++ if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
++ lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$'
++ else
++ lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
++ fi
++ ;;
++
++osf3* | osf4* | osf5*)
++ lt_cv_deplibs_check_method=pass_all
++ ;;
++
++rdos*)
++ lt_cv_deplibs_check_method=pass_all
++ ;;
++
++solaris*)
++ lt_cv_deplibs_check_method=pass_all
++ ;;
++
++sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
++ lt_cv_deplibs_check_method=pass_all
++ ;;
++
++sysv4 | sysv4.3*)
++ case $host_vendor in
++ motorola)
++ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]'
++ lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
++ ;;
++ ncr)
++ lt_cv_deplibs_check_method=pass_all
++ ;;
++ sequent)
++ lt_cv_file_magic_cmd='/bin/file'
++ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )'
++ ;;
++ sni)
++ lt_cv_file_magic_cmd='/bin/file'
++ lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib"
++ lt_cv_file_magic_test_file=/lib/libc.so
++ ;;
++ siemens)
++ lt_cv_deplibs_check_method=pass_all
++ ;;
++ pc)
++ lt_cv_deplibs_check_method=pass_all
++ ;;
++ esac
++ ;;
++
++tpf*)
++ lt_cv_deplibs_check_method=pass_all
++ ;;
++os2*)
++ lt_cv_deplibs_check_method=pass_all
++ ;;
++esac
++])
++
++file_magic_glob=
++want_nocaseglob=no
++if test "$build" = "$host"; then
++ case $host_os in
++ mingw* | pw32*)
++ if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then
++ want_nocaseglob=yes
++ else
++ file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"`
++ fi
++ ;;
++ esac
++fi
++
++file_magic_cmd=$lt_cv_file_magic_cmd
++deplibs_check_method=$lt_cv_deplibs_check_method
++test -z "$deplibs_check_method" && deplibs_check_method=unknown
++
++_LT_DECL([], [deplibs_check_method], [1],
++ [Method to check whether dependent libraries are shared objects])
++_LT_DECL([], [file_magic_cmd], [1],
++ [Command to use when deplibs_check_method = "file_magic"])
++_LT_DECL([], [file_magic_glob], [1],
++ [How to find potential files when deplibs_check_method = "file_magic"])
++_LT_DECL([], [want_nocaseglob], [1],
++ [Find potential files using nocaseglob when deplibs_check_method = "file_magic"])
++])# _LT_CHECK_MAGIC_METHOD
++
++
++# LT_PATH_NM
++# ----------
++# find the pathname to a BSD- or MS-compatible name lister
++AC_DEFUN([LT_PATH_NM],
++[AC_REQUIRE([AC_PROG_CC])dnl
++AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM,
++[if test -n "$NM"; then
++ # Let the user override the test.
++ lt_cv_path_NM=$NM
++else
++ lt_nm_to_check=${ac_tool_prefix}nm
++ if test -n "$ac_tool_prefix" && test "$build" = "$host"; then
++ lt_nm_to_check="$lt_nm_to_check nm"
++ fi
++ for lt_tmp_nm in $lt_nm_to_check; do
++ lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
++ for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do
++ IFS=$lt_save_ifs
++ test -z "$ac_dir" && ac_dir=.
++ tmp_nm=$ac_dir/$lt_tmp_nm
++ if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then
++ # Check to see if the nm accepts a BSD-compat flag.
++ # Adding the 'sed 1q' prevents false positives on HP-UX, which says:
++ # nm: unknown option "B" ignored
++ # Tru64's nm complains that /dev/null is an invalid object file
++ # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty
++ case $build_os in
++ mingw*) lt_bad_file=conftest.nm/nofile ;;
++ *) lt_bad_file=/dev/null ;;
++ esac
++ case `"$tmp_nm" -B $lt_bad_file 2>&1 | $SED '1q'` in
++ *$lt_bad_file* | *'Invalid file or object type'*)
++ lt_cv_path_NM="$tmp_nm -B"
++ break 2
++ ;;
++ *)
++ case `"$tmp_nm" -p /dev/null 2>&1 | $SED '1q'` in
++ */dev/null*)
++ lt_cv_path_NM="$tmp_nm -p"
++ break 2
++ ;;
++ *)
++ lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
++ continue # so that we can try to find one that supports BSD flags
++ ;;
++ esac
++ ;;
++ esac
++ fi
++ done
++ IFS=$lt_save_ifs
++ done
++ : ${lt_cv_path_NM=no}
++fi])
++if test no != "$lt_cv_path_NM"; then
++ NM=$lt_cv_path_NM
++else
++ # Didn't find any BSD compatible name lister, look for dumpbin.
++ if test -n "$DUMPBIN"; then :
++ # Let the user override the test.
++ else
++ AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :)
++ case `$DUMPBIN -symbols -headers /dev/null 2>&1 | $SED '1q'` in
++ *COFF*)
++ DUMPBIN="$DUMPBIN -symbols -headers"
++ ;;
++ *)
++ DUMPBIN=:
++ ;;
++ esac
++ fi
++ AC_SUBST([DUMPBIN])
++ if test : != "$DUMPBIN"; then
++ NM=$DUMPBIN
++ fi
++fi
++test -z "$NM" && NM=nm
++AC_SUBST([NM])
++_LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl
++
++AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface],
++ [lt_cv_nm_interface="BSD nm"
++ echo "int some_variable = 0;" > conftest.$ac_ext
++ (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD)
++ (eval "$ac_compile" 2>conftest.err)
++ cat conftest.err >&AS_MESSAGE_LOG_FD
++ (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD)
++ (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
++ cat conftest.err >&AS_MESSAGE_LOG_FD
++ (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD)
++ cat conftest.out >&AS_MESSAGE_LOG_FD
++ if $GREP 'External.*some_variable' conftest.out > /dev/null; then
++ lt_cv_nm_interface="MS dumpbin"
++ fi
++ rm -f conftest*])
++])# LT_PATH_NM
++
++# Old names:
++AU_ALIAS([AM_PROG_NM], [LT_PATH_NM])
++AU_ALIAS([AC_PROG_NM], [LT_PATH_NM])
++dnl aclocal-1.4 backwards compatibility:
++dnl AC_DEFUN([AM_PROG_NM], [])
++dnl AC_DEFUN([AC_PROG_NM], [])
++
++# _LT_CHECK_SHAREDLIB_FROM_LINKLIB
++# --------------------------------
++# how to determine the name of the shared library
++# associated with a specific link library.
++# -- PORTME fill in with the dynamic library characteristics
++m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB],
++[m4_require([_LT_DECL_EGREP])
++m4_require([_LT_DECL_OBJDUMP])
++m4_require([_LT_DECL_DLLTOOL])
++AC_CACHE_CHECK([how to associate runtime and link libraries],
++lt_cv_sharedlib_from_linklib_cmd,
++[lt_cv_sharedlib_from_linklib_cmd='unknown'
++
++case $host_os in
++cygwin* | mingw* | pw32* | cegcc*)
++ # two different shell functions defined in ltmain.sh;
++ # decide which one to use based on capabilities of $DLLTOOL
++ case `$DLLTOOL --help 2>&1` in
++ *--identify-strict*)
++ lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib
++ ;;
++ *)
++ lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback
++ ;;
++ esac
++ ;;
++*)
++ # fallback: assume linklib IS sharedlib
++ lt_cv_sharedlib_from_linklib_cmd=$ECHO
++ ;;
++esac
++])
++sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd
++test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO
++
++_LT_DECL([], [sharedlib_from_linklib_cmd], [1],
++ [Command to associate shared and link libraries])
++])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB
++
++
++# _LT_PATH_MANIFEST_TOOL
++# ----------------------
++# locate the manifest tool
++m4_defun([_LT_PATH_MANIFEST_TOOL],
++[AC_CHECK_TOOL(MANIFEST_TOOL, mt, :)
++test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt
++AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool],
++ [lt_cv_path_mainfest_tool=no
++ echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD
++ $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out
++ cat conftest.err >&AS_MESSAGE_LOG_FD
++ if $GREP 'Manifest Tool' conftest.out > /dev/null; then
++ lt_cv_path_mainfest_tool=yes
++ fi
++ rm -f conftest*])
++if test yes != "$lt_cv_path_mainfest_tool"; then
++ MANIFEST_TOOL=:
++fi
++_LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl
++])# _LT_PATH_MANIFEST_TOOL
++
++
++# _LT_DLL_DEF_P([FILE])
++# ---------------------
++# True iff FILE is a Windows DLL '.def' file.
++# Keep in sync with func_dll_def_p in the libtool script
++AC_DEFUN([_LT_DLL_DEF_P],
++[dnl
++ test DEF = "`$SED -n dnl
++ -e '\''s/^[[ ]]*//'\'' dnl Strip leading whitespace
++ -e '\''/^\(;.*\)*$/d'\'' dnl Delete empty lines and comments
++ -e '\''s/^\(EXPORTS\|LIBRARY\)\([[ ]].*\)*$/DEF/p'\'' dnl
++ -e q dnl Only consider the first "real" line
++ $1`" dnl
++])# _LT_DLL_DEF_P
++
++
++# LT_LIB_M
++# --------
++# check for math library
++AC_DEFUN([LT_LIB_M],
++[AC_REQUIRE([AC_CANONICAL_HOST])dnl
++LIBM=
++case $host in
++*-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*)
++ # These system don't have libm, or don't need it
++ ;;
++*-ncr-sysv4.3*)
++ AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM=-lmw)
++ AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm")
++ ;;
++*)
++ AC_CHECK_LIB(m, cos, LIBM=-lm)
++ ;;
++esac
++AC_SUBST([LIBM])
++])# LT_LIB_M
++
++# Old name:
++AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M])
++dnl aclocal-1.4 backwards compatibility:
++dnl AC_DEFUN([AC_CHECK_LIBM], [])
++
++
++# _LT_COMPILER_NO_RTTI([TAGNAME])
++# -------------------------------
++m4_defun([_LT_COMPILER_NO_RTTI],
++[m4_require([_LT_TAG_COMPILER])dnl
++
++_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
++
++if test yes = "$GCC"; then
++ case $cc_basename in
++ nvcc*)
++ _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;;
++ *)
++ _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;;
++ esac
++
++ _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions],
++ lt_cv_prog_compiler_rtti_exceptions,
++ [-fno-rtti -fno-exceptions], [],
++ [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"])
++fi
++_LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1],
++ [Compiler flag to turn off builtin functions])
++])# _LT_COMPILER_NO_RTTI
++
++
++# _LT_CMD_GLOBAL_SYMBOLS
++# ----------------------
++m4_defun([_LT_CMD_GLOBAL_SYMBOLS],
++[AC_REQUIRE([AC_CANONICAL_HOST])dnl
++AC_REQUIRE([AC_PROG_CC])dnl
++AC_REQUIRE([AC_PROG_AWK])dnl
++AC_REQUIRE([LT_PATH_NM])dnl
++AC_REQUIRE([LT_PATH_LD])dnl
++m4_require([_LT_DECL_SED])dnl
++m4_require([_LT_DECL_EGREP])dnl
++m4_require([_LT_TAG_COMPILER])dnl
++
++# Check for command to grab the raw symbol name followed by C symbol from nm.
++AC_MSG_CHECKING([command to parse $NM output from $compiler object])
++AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe],
++[
++# These are sane defaults that work on at least a few old systems.
++# [They come from Ultrix. What could be older than Ultrix?!! ;)]
++
++# Character class describing NM global symbol codes.
++symcode='[[BCDEGRST]]'
++
++# Regexp to match symbols that can be accessed directly from C.
++sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)'
++
++# Define system-specific variables.
++case $host_os in
++aix*)
++ symcode='[[BCDT]]'
++ ;;
++cygwin* | mingw* | pw32* | cegcc*)
++ symcode='[[ABCDGISTW]]'
++ ;;
++hpux*)
++ if test ia64 = "$host_cpu"; then
++ symcode='[[ABCDEGRST]]'
++ fi
++ ;;
++irix* | nonstopux*)
++ symcode='[[BCDEGRST]]'
++ ;;
++osf*)
++ symcode='[[BCDEGQRST]]'
++ ;;
++solaris*)
++ symcode='[[BDRT]]'
++ ;;
++sco3.2v5*)
++ symcode='[[DT]]'
++ ;;
++sysv4.2uw2*)
++ symcode='[[DT]]'
++ ;;
++sysv5* | sco5v6* | unixware* | OpenUNIX*)
++ symcode='[[ABDT]]'
++ ;;
++sysv4)
++ symcode='[[DFNSTU]]'
++ ;;
++esac
++
++# If we're using GNU nm, then use its standard symbol codes.
++case `$NM -V 2>&1` in
++*GNU* | *'with BFD'*)
++ symcode='[[ABCDGIRSTW]]' ;;
++esac
++
++if test "$lt_cv_nm_interface" = "MS dumpbin"; then
++ # Gets list of data symbols to import.
++ lt_cv_sys_global_symbol_to_import="$SED -n -e 's/^I .* \(.*\)$/\1/p'"
++ # Adjust the below global symbol transforms to fixup imported variables.
++ lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'"
++ lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'"
++ lt_c_name_lib_hook="\
++ -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\
++ -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'"
++else
++ # Disable hooks by default.
++ lt_cv_sys_global_symbol_to_import=
++ lt_cdecl_hook=
++ lt_c_name_hook=
++ lt_c_name_lib_hook=
++fi
++
++# Transform an extracted symbol line into a proper C declaration.
++# Some systems (esp. on ia64) link data and code symbols differently,
++# so use this general approach.
++lt_cv_sys_global_symbol_to_cdecl="$SED -n"\
++$lt_cdecl_hook\
++" -e 's/^T .* \(.*\)$/extern int \1();/p'"\
++" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'"
++
++# Transform an extracted symbol line into symbol name and symbol address
++lt_cv_sys_global_symbol_to_c_name_address="$SED -n"\
++$lt_c_name_hook\
++" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\
++" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'"
++
++# Transform an extracted symbol line into symbol name with lib prefix and
++# symbol address.
++lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="$SED -n"\
++$lt_c_name_lib_hook\
++" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\
++" -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\
++" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'"
++
++# Handle CRLF in mingw tool chain
++opt_cr=
++case $build_os in
++mingw*)
++ opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp
++ ;;
++esac
++
++# Try without a prefix underscore, then with it.
++for ac_symprfx in "" "_"; do
++
++ # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol.
++ symxfrm="\\1 $ac_symprfx\\2 \\2"
++
++ # Write the raw and C identifiers.
++ if test "$lt_cv_nm_interface" = "MS dumpbin"; then
++ # Fake it for dumpbin and say T for any non-static function,
++ # D for any global variable and I for any imported variable.
++ # Also find C++ and __fastcall symbols from MSVC++ or ICC,
++ # which start with @ or ?.
++ lt_cv_sys_global_symbol_pipe="$AWK ['"\
++" {last_section=section; section=\$ 3};"\
++" /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\
++" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\
++" /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\
++" /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\
++" /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\
++" \$ 0!~/External *\|/{next};"\
++" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\
++" {if(hide[section]) next};"\
++" {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\
++" {split(\$ 0,a,/\||\r/); split(a[2],s)};"\
++" s[1]~/^[@?]/{print f,s[1],s[1]; next};"\
++" s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\
++" ' prfx=^$ac_symprfx]"
++ else
++ lt_cv_sys_global_symbol_pipe="$SED -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
++ fi
++ lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | $SED '/ __gnu_lto/d'"
++
++ # Check to see that the pipe works correctly.
++ pipe_works=no
++
++ rm -f conftest*
++ cat > conftest.$ac_ext <<_LT_EOF
++#ifdef __cplusplus
++extern "C" {
++#endif
++char nm_test_var;
++void nm_test_func(void);
++void nm_test_func(void){}
++#ifdef __cplusplus
++}
++#endif
++int main(){nm_test_var='a';nm_test_func();return(0);}
++_LT_EOF
++
++ if AC_TRY_EVAL(ac_compile); then
++ # Now try to grab the symbols.
++ nlist=conftest.nm
++ if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then
++ # Try sorting and uniquifying the output.
++ if sort "$nlist" | uniq > "$nlist"T; then
++ mv -f "$nlist"T "$nlist"
++ else
++ rm -f "$nlist"T
++ fi
++
++ # Make sure that we snagged all the symbols we need.
++ if $GREP ' nm_test_var$' "$nlist" >/dev/null; then
++ if $GREP ' nm_test_func$' "$nlist" >/dev/null; then
++ cat <<_LT_EOF > conftest.$ac_ext
++/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */
++#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE
++/* DATA imports from DLLs on WIN32 can't be const, because runtime
++ relocations are performed -- see ld's documentation on pseudo-relocs. */
++# define LT@&t@_DLSYM_CONST
++#elif defined __osf__
++/* This system does not cope well with relocations in const data. */
++# define LT@&t@_DLSYM_CONST
++#else
++# define LT@&t@_DLSYM_CONST const
++#endif
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++_LT_EOF
++ # Now generate the symbol file.
++ eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext'
++
++ cat <<_LT_EOF >> conftest.$ac_ext
++
++/* The mapping between symbol names and symbols. */
++LT@&t@_DLSYM_CONST struct {
++ const char *name;
++ void *address;
++}
++lt__PROGRAM__LTX_preloaded_symbols[[]] =
++{
++ { "@PROGRAM@", (void *) 0 },
++_LT_EOF
++ $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext
++ cat <<\_LT_EOF >> conftest.$ac_ext
++ {0, (void *) 0}
++};
++
++/* This works around a problem in FreeBSD linker */
++#ifdef FREEBSD_WORKAROUND
++static const void *lt_preloaded_setup() {
++ return lt__PROGRAM__LTX_preloaded_symbols;
++}
++#endif
++
++#ifdef __cplusplus
++}
++#endif
++_LT_EOF
++ # Now try linking the two files.
++ mv conftest.$ac_objext conftstm.$ac_objext
++ lt_globsym_save_LIBS=$LIBS
++ lt_globsym_save_CFLAGS=$CFLAGS
++ LIBS=conftstm.$ac_objext
++ CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)"
++ if AC_TRY_EVAL(ac_link) && test -s conftest$ac_exeext; then
++ pipe_works=yes
++ fi
++ LIBS=$lt_globsym_save_LIBS
++ CFLAGS=$lt_globsym_save_CFLAGS
++ else
++ echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD
++ fi
++ else
++ echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD
++ fi
++ else
++ echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD
++ fi
++ else
++ echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD
++ cat conftest.$ac_ext >&5
++ fi
++ rm -rf conftest* conftst*
++
++ # Do not use the global_symbol_pipe unless it works.
++ if test yes = "$pipe_works"; then
++ break
++ else
++ lt_cv_sys_global_symbol_pipe=
++ fi
++done
++])
++if test -z "$lt_cv_sys_global_symbol_pipe"; then
++ lt_cv_sys_global_symbol_to_cdecl=
++fi
++if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
++ AC_MSG_RESULT(failed)
++else
++ AC_MSG_RESULT(ok)
++fi
++
++# Response file support.
++if test "$lt_cv_nm_interface" = "MS dumpbin"; then
++ nm_file_list_spec='@'
++elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then
++ nm_file_list_spec='@'
++fi
++
++_LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1],
++ [Take the output of nm and produce a listing of raw symbols and C names])
++_LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1],
++ [Transform the output of nm in a proper C declaration])
++_LT_DECL([global_symbol_to_import], [lt_cv_sys_global_symbol_to_import], [1],
++ [Transform the output of nm into a list of symbols to manually relocate])
++_LT_DECL([global_symbol_to_c_name_address],
++ [lt_cv_sys_global_symbol_to_c_name_address], [1],
++ [Transform the output of nm in a C name address pair])
++_LT_DECL([global_symbol_to_c_name_address_lib_prefix],
++ [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1],
++ [Transform the output of nm in a C name address pair when lib prefix is needed])
++_LT_DECL([nm_interface], [lt_cv_nm_interface], [1],
++ [The name lister interface])
++_LT_DECL([], [nm_file_list_spec], [1],
++ [Specify filename containing input files for $NM])
++]) # _LT_CMD_GLOBAL_SYMBOLS
++
++
++# _LT_COMPILER_PIC([TAGNAME])
++# ---------------------------
++m4_defun([_LT_COMPILER_PIC],
++[m4_require([_LT_TAG_COMPILER])dnl
++_LT_TAGVAR(lt_prog_compiler_wl, $1)=
++_LT_TAGVAR(lt_prog_compiler_pic, $1)=
++_LT_TAGVAR(lt_prog_compiler_static, $1)=
++
++m4_if([$1], [CXX], [
++ # C++ specific cases for pic, static, wl, etc.
++ if test yes = "$GXX"; then
++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++ _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
++
++ case $host_os in
++ aix*)
++ # All AIX code is PIC.
++ if test ia64 = "$host_cpu"; then
++ # AIX 5 now supports IA64 processor
++ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
++ fi
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
++ ;;
++
++ amigaos*)
++ case $host_cpu in
++ powerpc)
++ # see comment about AmigaOS4 .so support
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
++ ;;
++ m68k)
++ # FIXME: we need at least 68020 code to build shared libraries, but
++ # adding the '-m68020' flag to GCC prevents building anything better,
++ # like '-m68040'.
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
++ ;;
++ esac
++ ;;
++
++ beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
++ # PIC is the default for these OSes.
++ ;;
++ mingw* | cygwin* | os2* | pw32* | cegcc*)
++ # This hack is so that the source file can tell whether it is being
++ # built for inclusion in a dll (and should export symbols for example).
++ # Although the cygwin gcc ignores -fPIC, still need this for old-style
++ # (--disable-auto-import) libraries
++ m4_if([$1], [GCJ], [],
++ [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
++ case $host_os in
++ os2*)
++ _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static'
++ ;;
++ esac
++ ;;
++ darwin* | rhapsody*)
++ # PIC is the default on this platform
++ # Common symbols not allowed in MH_DYLIB files
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
++ ;;
++ *djgpp*)
++ # DJGPP does not support shared libraries at all
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)=
++ ;;
++ haiku*)
++ # PIC is the default for Haiku.
++ # The "-static" flag exists, but is broken.
++ _LT_TAGVAR(lt_prog_compiler_static, $1)=
++ ;;
++ interix[[3-9]]*)
++ # Interix 3.x gcc -fpic/-fPIC options generate broken code.
++ # Instead, we relocate shared libraries at runtime.
++ ;;
++ sysv4*MP*)
++ if test -d /usr/nec; then
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
++ fi
++ ;;
++ hpux*)
++ # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
++ # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag
++ # sets the default TLS model and affects inlining.
++ case $host_cpu in
++ hppa*64*)
++ ;;
++ *)
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
++ ;;
++ esac
++ ;;
++ *qnx* | *nto*)
++ # QNX uses GNU C++, but need to define -shared option too, otherwise
++ # it will coredump.
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
++ ;;
++ *)
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
++ ;;
++ esac
++ else
++ case $host_os in
++ aix[[4-9]]*)
++ # All AIX code is PIC.
++ if test ia64 = "$host_cpu"; then
++ # AIX 5 now supports IA64 processor
++ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
++ else
++ _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
++ fi
++ ;;
++ chorus*)
++ case $cc_basename in
++ cxch68*)
++ # Green Hills C++ Compiler
++ # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a"
++ ;;
++ esac
++ ;;
++ mingw* | cygwin* | os2* | pw32* | cegcc*)
++ # This hack is so that the source file can tell whether it is being
++ # built for inclusion in a dll (and should export symbols for example).
++ m4_if([$1], [GCJ], [],
++ [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
++ ;;
++ dgux*)
++ case $cc_basename in
++ ec++*)
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
++ ;;
++ ghcx*)
++ # Green Hills C++ Compiler
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
++ ;;
++ *)
++ ;;
++ esac
++ ;;
++ freebsd* | dragonfly* | midnightbsd*)
++ # FreeBSD uses GNU C++
++ ;;
++ hpux9* | hpux10* | hpux11*)
++ case $cc_basename in
++ CC*)
++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++ _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive'
++ if test ia64 != "$host_cpu"; then
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
++ fi
++ ;;
++ aCC*)
++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++ _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive'
++ case $host_cpu in
++ hppa*64*|ia64*)
++ # +Z the default
++ ;;
++ *)
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
++ ;;
++ esac
++ ;;
++ *)
++ ;;
++ esac
++ ;;
++ interix*)
++ # This is c89, which is MS Visual C++ (no shared libs)
++ # Anyone wants to do a port?
++ ;;
++ irix5* | irix6* | nonstopux*)
++ case $cc_basename in
++ CC*)
++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++ _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
++ # CC pic flag -KPIC is the default.
++ ;;
++ *)
++ ;;
++ esac
++ ;;
++ linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
++ case $cc_basename in
++ KCC*)
++ # KAI C++ Compiler
++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
++ ;;
++ ecpc* )
++ # old Intel C++ for x86_64, which still supported -KPIC.
++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
++ _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
++ ;;
++ icpc* )
++ # Intel C++, used to be incompatible with GCC.
++ # ICC 10 doesn't accept -KPIC any more.
++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
++ _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
++ ;;
++ pgCC* | pgcpp*)
++ # Portland Group C++ compiler
++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
++ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
++ ;;
++ cxx*)
++ # Compaq C++
++ # Make sure the PIC flag is empty. It appears that all Alpha
++ # Linux and Compaq Tru64 Unix objects are PIC.
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)=
++ _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
++ ;;
++ xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*)
++ # IBM XL 8.0, 9.0 on PPC and BlueGene
++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic'
++ _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink'
++ ;;
++ *)
++ case `$CC -V 2>&1 | $SED 5q` in
++ *Sun\ C*)
++ # Sun C++ 5.9
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
++ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
++ ;;
++ esac
++ ;;
++ esac
++ ;;
++ lynxos*)
++ ;;
++ m88k*)
++ ;;
++ mvs*)
++ case $cc_basename in
++ cxx*)
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall'
++ ;;
++ *)
++ ;;
++ esac
++ ;;
++ netbsd*)
++ ;;
++ *qnx* | *nto*)
++ # QNX uses GNU C++, but need to define -shared option too, otherwise
++ # it will coredump.
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
++ ;;
++ osf3* | osf4* | osf5*)
++ case $cc_basename in
++ KCC*)
++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
++ ;;
++ RCC*)
++ # Rational C++ 2.4.1
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
++ ;;
++ cxx*)
++ # Digital/Compaq C++
++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++ # Make sure the PIC flag is empty. It appears that all Alpha
++ # Linux and Compaq Tru64 Unix objects are PIC.
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)=
++ _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
++ ;;
++ *)
++ ;;
++ esac
++ ;;
++ psos*)
++ ;;
++ solaris*)
++ case $cc_basename in
++ CC* | sunCC*)
++ # Sun C++ 4.2, 5.x and Centerline C++
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
++ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
++ ;;
++ gcx*)
++ # Green Hills C++ Compiler
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
++ ;;
++ *)
++ ;;
++ esac
++ ;;
++ sunos4*)
++ case $cc_basename in
++ CC*)
++ # Sun C++ 4.x
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
++ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
++ ;;
++ lcc*)
++ # Lucid
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
++ ;;
++ *)
++ ;;
++ esac
++ ;;
++ sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
++ case $cc_basename in
++ CC*)
++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
++ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
++ ;;
++ esac
++ ;;
++ tandem*)
++ case $cc_basename in
++ NCC*)
++ # NonStop-UX NCC 3.20
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
++ ;;
++ *)
++ ;;
++ esac
++ ;;
++ vxworks*)
++ ;;
++ *)
++ _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
++ ;;
++ esac
++ fi
++],
++[
++ if test yes = "$GCC"; then
++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++ _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
++
++ case $host_os in
++ aix*)
++ # All AIX code is PIC.
++ if test ia64 = "$host_cpu"; then
++ # AIX 5 now supports IA64 processor
++ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
++ fi
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
++ ;;
++
++ amigaos*)
++ case $host_cpu in
++ powerpc)
++ # see comment about AmigaOS4 .so support
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
++ ;;
++ m68k)
++ # FIXME: we need at least 68020 code to build shared libraries, but
++ # adding the '-m68020' flag to GCC prevents building anything better,
++ # like '-m68040'.
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
++ ;;
++ esac
++ ;;
++
++ beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
++ # PIC is the default for these OSes.
++ ;;
++
++ mingw* | cygwin* | pw32* | os2* | cegcc*)
++ # This hack is so that the source file can tell whether it is being
++ # built for inclusion in a dll (and should export symbols for example).
++ # Although the cygwin gcc ignores -fPIC, still need this for old-style
++ # (--disable-auto-import) libraries
++ m4_if([$1], [GCJ], [],
++ [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
++ case $host_os in
++ os2*)
++ _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static'
++ ;;
++ esac
++ ;;
++
++ darwin* | rhapsody*)
++ # PIC is the default on this platform
++ # Common symbols not allowed in MH_DYLIB files
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
++ ;;
++
++ haiku*)
++ # PIC is the default for Haiku.
++ # The "-static" flag exists, but is broken.
++ _LT_TAGVAR(lt_prog_compiler_static, $1)=
++ ;;
++
++ hpux*)
++ # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
++ # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag
++ # sets the default TLS model and affects inlining.
++ case $host_cpu in
++ hppa*64*)
++ # +Z the default
++ ;;
++ *)
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
++ ;;
++ esac
++ ;;
++
++ interix[[3-9]]*)
++ # Interix 3.x gcc -fpic/-fPIC options generate broken code.
++ # Instead, we relocate shared libraries at runtime.
++ ;;
++
++ msdosdjgpp*)
++ # Just because we use GCC doesn't mean we suddenly get shared libraries
++ # on systems that don't support them.
++ _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
++ enable_shared=no
++ ;;
++
++ *nto* | *qnx*)
++ # QNX uses GNU C++, but need to define -shared option too, otherwise
++ # it will coredump.
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
++ ;;
++
++ sysv4*MP*)
++ if test -d /usr/nec; then
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
++ fi
++ ;;
++
++ *)
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
++ ;;
++ esac
++
++ case $cc_basename in
++ nvcc*) # Cuda Compiler Driver 2.2
++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker '
++ if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)"
++ fi
++ ;;
++ esac
++ else
++ # PORTME Check for flag to pass linker flags through the system compiler.
++ case $host_os in
++ aix*)
++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++ if test ia64 = "$host_cpu"; then
++ # AIX 5 now supports IA64 processor
++ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
++ else
++ _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
++ fi
++ ;;
++
++ darwin* | rhapsody*)
++ # PIC is the default on this platform
++ # Common symbols not allowed in MH_DYLIB files
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
++ case $cc_basename in
++ nagfor*)
++ # NAG Fortran compiler
++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,'
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
++ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
++ ;;
++ esac
++ ;;
++
++ mingw* | cygwin* | pw32* | os2* | cegcc*)
++ # This hack is so that the source file can tell whether it is being
++ # built for inclusion in a dll (and should export symbols for example).
++ m4_if([$1], [GCJ], [],
++ [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
++ case $host_os in
++ os2*)
++ _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static'
++ ;;
++ esac
++ ;;
++
++ hpux9* | hpux10* | hpux11*)
++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
++ # not for PA HP-UX.
++ case $host_cpu in
++ hppa*64*|ia64*)
++ # +Z the default
++ ;;
++ *)
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
++ ;;
++ esac
++ # Is there a better lt_prog_compiler_static that works with the bundled CC?
++ _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive'
++ ;;
++
++ irix5* | irix6* | nonstopux*)
++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++ # PIC (with -KPIC) is the default.
++ _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
++ ;;
++
++ linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
++ case $cc_basename in
++ # old Intel for x86_64, which still supported -KPIC.
++ ecc*)
++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
++ _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
++ ;;
++ # icc used to be incompatible with GCC.
++ # ICC 10 doesn't accept -KPIC any more.
++ icc* | ifort*)
++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
++ _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
++ ;;
++ # Lahey Fortran 8.1.
++ lf95*)
++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared'
++ _LT_TAGVAR(lt_prog_compiler_static, $1)='--static'
++ ;;
++ nagfor*)
++ # NAG Fortran compiler
++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,'
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
++ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
++ ;;
++ tcc*)
++ # Fabrice Bellard et al's Tiny C Compiler
++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
++ _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
++ ;;
++ pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*)
++ # Portland Group compilers (*not* the Pentium gcc compiler,
++ # which looks to be a dead project)
++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
++ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
++ ;;
++ ccc*)
++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++ # All Alpha code is PIC.
++ _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
++ ;;
++ xl* | bgxl* | bgf* | mpixl*)
++ # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene
++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic'
++ _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink'
++ ;;
++ *)
++ case `$CC -V 2>&1 | $SED 5q` in
++ *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*)
++ # Sun Fortran 8.3 passes all unrecognized flags to the linker
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
++ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
++ _LT_TAGVAR(lt_prog_compiler_wl, $1)=''
++ ;;
++ *Sun\ F* | *Sun*Fortran*)
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
++ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
++ ;;
++ *Sun\ C*)
++ # Sun C 5.9
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
++ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++ ;;
++ *Intel*\ [[CF]]*Compiler*)
++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
++ _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
++ ;;
++ *Portland\ Group*)
++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
++ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
++ ;;
++ esac
++ ;;
++ esac
++ ;;
++
++ newsos6)
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
++ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
++ ;;
++
++ *nto* | *qnx*)
++ # QNX uses GNU C++, but need to define -shared option too, otherwise
++ # it will coredump.
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
++ ;;
++
++ osf3* | osf4* | osf5*)
++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++ # All OSF/1 code is PIC.
++ _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
++ ;;
++
++ rdos*)
++ _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
++ ;;
++
++ solaris*)
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
++ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
++ case $cc_basename in
++ f77* | f90* | f95* | sunf77* | sunf90* | sunf95*)
++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';;
++ *)
++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';;
++ esac
++ ;;
++
++ sunos4*)
++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
++ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
++ ;;
++
++ sysv4 | sysv4.2uw2* | sysv4.3*)
++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
++ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
++ ;;
++
++ sysv4*MP*)
++ if test -d /usr/nec; then
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic'
++ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
++ fi
++ ;;
++
++ sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
++ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
++ ;;
++
++ unicos*)
++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++ _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
++ ;;
++
++ uts4*)
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
++ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
++ ;;
++
++ *)
++ _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
++ ;;
++ esac
++ fi
++])
++case $host_os in
++ # For platforms that do not support PIC, -DPIC is meaningless:
++ *djgpp*)
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)=
++ ;;
++ *)
++ _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])"
++ ;;
++esac
++
++AC_CACHE_CHECK([for $compiler option to produce PIC],
++ [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)],
++ [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)])
++_LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)
++
++#
++# Check to make sure the PIC flag actually works.
++#
++if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then
++ _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works],
++ [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)],
++ [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [],
++ [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in
++ "" | " "*) ;;
++ *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;;
++ esac],
++ [_LT_TAGVAR(lt_prog_compiler_pic, $1)=
++ _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no])
++fi
++_LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1],
++ [Additional compiler flags for building library objects])
++
++_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1],
++ [How to pass a linker flag through the compiler])
++#
++# Check to make sure the static flag actually works.
++#
++wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\"
++_LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works],
++ _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1),
++ $lt_tmp_static_flag,
++ [],
++ [_LT_TAGVAR(lt_prog_compiler_static, $1)=])
++_LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1],
++ [Compiler flag to prevent dynamic linking])
++])# _LT_COMPILER_PIC
++
++
++# _LT_LINKER_SHLIBS([TAGNAME])
++# ----------------------------
++# See if the linker supports building shared libraries.
++m4_defun([_LT_LINKER_SHLIBS],
++[AC_REQUIRE([LT_PATH_LD])dnl
++AC_REQUIRE([LT_PATH_NM])dnl
++m4_require([_LT_PATH_MANIFEST_TOOL])dnl
++m4_require([_LT_FILEUTILS_DEFAULTS])dnl
++m4_require([_LT_DECL_EGREP])dnl
++m4_require([_LT_DECL_SED])dnl
++m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl
++m4_require([_LT_TAG_COMPILER])dnl
++AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
++m4_if([$1], [CXX], [
++ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
++ _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*']
++ case $host_os in
++ aix[[4-9]]*)
++ # If we're using GNU nm, then we don't want the "-C" option.
++ # -C means demangle to GNU nm, but means don't demangle to AIX nm.
++ # Without the "-l" option, or with the "-B" option, AIX nm treats
++ # weak defined symbols like other global defined symbols, whereas
++ # GNU nm marks them as "W".
++ # While the 'weak' keyword is ignored in the Export File, we need
++ # it in the Import File for the 'aix-soname' feature, so we have
++ # to replace the "-B" option with "-P" for AIX nm.
++ if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
++ _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols'
++ else
++ _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "L") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols'
++ fi
++ ;;
++ pw32*)
++ _LT_TAGVAR(export_symbols_cmds, $1)=$ltdll_cmds
++ ;;
++ cygwin* | mingw* | cegcc*)
++ case $cc_basename in
++ cl* | icl*)
++ _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*'
++ ;;
++ *)
++ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols'
++ _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname']
++ ;;
++ esac
++ ;;
++ *)
++ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
++ ;;
++ esac
++], [
++ runpath_var=
++ _LT_TAGVAR(allow_undefined_flag, $1)=
++ _LT_TAGVAR(always_export_symbols, $1)=no
++ _LT_TAGVAR(archive_cmds, $1)=
++ _LT_TAGVAR(archive_expsym_cmds, $1)=
++ _LT_TAGVAR(compiler_needs_object, $1)=no
++ _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
++ _LT_TAGVAR(export_dynamic_flag_spec, $1)=
++ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
++ _LT_TAGVAR(hardcode_automatic, $1)=no
++ _LT_TAGVAR(hardcode_direct, $1)=no
++ _LT_TAGVAR(hardcode_direct_absolute, $1)=no
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
++ _LT_TAGVAR(hardcode_libdir_separator, $1)=
++ _LT_TAGVAR(hardcode_minus_L, $1)=no
++ _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
++ _LT_TAGVAR(inherit_rpath, $1)=no
++ _LT_TAGVAR(link_all_deplibs, $1)=unknown
++ _LT_TAGVAR(module_cmds, $1)=
++ _LT_TAGVAR(module_expsym_cmds, $1)=
++ _LT_TAGVAR(old_archive_from_new_cmds, $1)=
++ _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)=
++ _LT_TAGVAR(thread_safe_flag_spec, $1)=
++ _LT_TAGVAR(whole_archive_flag_spec, $1)=
++ # include_expsyms should be a list of space-separated symbols to be *always*
++ # included in the symbol list
++ _LT_TAGVAR(include_expsyms, $1)=
++ # exclude_expsyms can be an extended regexp of symbols to exclude
++ # it will be wrapped by ' (' and ')$', so one must not match beginning or
++ # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc',
++ # as well as any symbol that contains 'd'.
++ _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*']
++ # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
++ # platforms (ab)use it in PIC code, but their linkers get confused if
++ # the symbol is explicitly referenced. Since portable code cannot
++ # rely on this symbol name, it's probably fine to never include it in
++ # preloaded symbol tables.
++ # Exclude shared library initialization/finalization symbols.
++dnl Note also adjust exclude_expsyms for C++ above.
++ extract_expsyms_cmds=
++
++ case $host_os in
++ cygwin* | mingw* | pw32* | cegcc*)
++ # FIXME: the MSVC++ and ICC port hasn't been tested in a loooong time
++ # When not using gcc, we currently assume that we are using
++ # Microsoft Visual C++ or Intel C++ Compiler.
++ if test yes != "$GCC"; then
++ with_gnu_ld=no
++ fi
++ ;;
++ interix*)
++ # we just hope/assume this is gcc and not c89 (= MSVC++ or ICC)
++ with_gnu_ld=yes
++ ;;
++ openbsd* | bitrig*)
++ with_gnu_ld=no
++ ;;
++ esac
++
++ _LT_TAGVAR(ld_shlibs, $1)=yes
++
++ # On some targets, GNU ld is compatible enough with the native linker
++ # that we're better off using the native interface for both.
++ lt_use_gnu_ld_interface=no
++ if test yes = "$with_gnu_ld"; then
++ case $host_os in
++ aix*)
++ # The AIX port of GNU ld has always aspired to compatibility
++ # with the native linker. However, as the warning in the GNU ld
++ # block says, versions before 2.19.5* couldn't really create working
++ # shared libraries, regardless of the interface used.
++ case `$LD -v 2>&1` in
++ *\ \(GNU\ Binutils\)\ 2.19.5*) ;;
++ *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;;
++ *\ \(GNU\ Binutils\)\ [[3-9]]*) ;;
++ *)
++ lt_use_gnu_ld_interface=yes
++ ;;
++ esac
++ ;;
++ *)
++ lt_use_gnu_ld_interface=yes
++ ;;
++ esac
++ fi
++
++ if test yes = "$lt_use_gnu_ld_interface"; then
++ # If archive_cmds runs LD, not CC, wlarc should be empty
++ wlarc='$wl'
++
++ # Set some defaults for GNU ld with shared library support. These
++ # are reset later if shared libraries are not supported. Putting them
++ # here allows them to be overridden if necessary.
++ runpath_var=LD_RUN_PATH
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
++ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
++ # ancient GNU ld didn't support --whole-archive et. al.
++ if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then
++ _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive'
++ else
++ _LT_TAGVAR(whole_archive_flag_spec, $1)=
++ fi
++ supports_anon_versioning=no
++ case `$LD -v | $SED -e 's/([[^)]]\+)\s\+//' 2>&1` in
++ *GNU\ gold*) supports_anon_versioning=yes ;;
++ *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11
++ *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
++ *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
++ *\ 2.11.*) ;; # other 2.11 versions
++ *) supports_anon_versioning=yes ;;
++ esac
++
++ # See if GNU ld supports shared libraries.
++ case $host_os in
++ aix[[3-9]]*)
++ # On AIX/PPC, the GNU linker is very broken
++ if test ia64 != "$host_cpu"; then
++ _LT_TAGVAR(ld_shlibs, $1)=no
++ cat <<_LT_EOF 1>&2
++
++*** Warning: the GNU linker, at least up to release 2.19, is reported
++*** to be unable to reliably create shared libraries on AIX.
++*** Therefore, libtool is disabling shared libraries support. If you
++*** really care for shared libraries, you may want to install binutils
++*** 2.20 or above, or modify your PATH so that a non-GNU linker is found.
++*** You will then need to restart the configuration process.
++
++_LT_EOF
++ fi
++ ;;
++
++ amigaos*)
++ case $host_cpu in
++ powerpc)
++ # see comment about AmigaOS4 .so support
++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
++ _LT_TAGVAR(archive_expsym_cmds, $1)=''
++ ;;
++ m68k)
++ _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
++ _LT_TAGVAR(hardcode_minus_L, $1)=yes
++ ;;
++ esac
++ ;;
++
++ beos*)
++ if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
++ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
++ # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
++ # support --undefined. This deserves some investigation. FIXME
++ _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
++ else
++ _LT_TAGVAR(ld_shlibs, $1)=no
++ fi
++ ;;
++
++ cygwin* | mingw* | pw32* | cegcc*)
++ # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
++ # as there is no search path for DLLs.
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
++ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols'
++ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
++ _LT_TAGVAR(always_export_symbols, $1)=no
++ _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
++ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols'
++ _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname']
++
++ if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
++ # If the export-symbols file already is a .def file, use it as
++ # is; otherwise, prepend EXPORTS...
++ _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then
++ cp $export_symbols $output_objdir/$soname.def;
++ else
++ echo EXPORTS > $output_objdir/$soname.def;
++ cat $export_symbols >> $output_objdir/$soname.def;
++ fi~
++ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
++ else
++ _LT_TAGVAR(ld_shlibs, $1)=no
++ fi
++ ;;
++
++ haiku*)
++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
++ _LT_TAGVAR(link_all_deplibs, $1)=yes
++ ;;
++
++ os2*)
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
++ _LT_TAGVAR(hardcode_minus_L, $1)=yes
++ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
++ shrext_cmds=.dll
++ _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
++ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
++ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
++ $ECHO EXPORTS >> $output_objdir/$libname.def~
++ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~
++ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
++ emximp -o $lib $output_objdir/$libname.def'
++ _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
++ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
++ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
++ $ECHO EXPORTS >> $output_objdir/$libname.def~
++ prefix_cmds="$SED"~
++ if test EXPORTS = "`$SED 1q $export_symbols`"; then
++ prefix_cmds="$prefix_cmds -e 1d";
++ fi~
++ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~
++ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~
++ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
++ emximp -o $lib $output_objdir/$libname.def'
++ _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
++ _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
++ _LT_TAGVAR(file_list_spec, $1)='@'
++ ;;
++
++ interix[[3-9]]*)
++ _LT_TAGVAR(hardcode_direct, $1)=no
++ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
++ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
++ # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
++ # Instead, shared libraries are loaded at an image base (0x10000000 by
++ # default) and relocated if they conflict, which is a slow very memory
++ # consuming and fragmenting process. To avoid this, we pick a random,
++ # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
++ # time. Moving up from 0x10000000 also allows more sbrk(2) space.
++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
++ _LT_TAGVAR(archive_expsym_cmds, $1)='$SED "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
++ ;;
++
++ gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu)
++ tmp_diet=no
++ if test linux-dietlibc = "$host_os"; then
++ case $cc_basename in
++ diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn)
++ esac
++ fi
++ if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \
++ && test no = "$tmp_diet"
++ then
++ tmp_addflag=' $pic_flag'
++ tmp_sharedflag='-shared'
++ case $cc_basename,$host_cpu in
++ pgcc*) # Portland Group C compiler
++ _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
++ tmp_addflag=' $pic_flag'
++ ;;
++ pgf77* | pgf90* | pgf95* | pgfortran*)
++ # Portland Group f77 and f90 compilers
++ _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
++ tmp_addflag=' $pic_flag -Mnomain' ;;
++ ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64
++ tmp_addflag=' -i_dynamic' ;;
++ efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64
++ tmp_addflag=' -i_dynamic -nofor_main' ;;
++ ifc* | ifort*) # Intel Fortran compiler
++ tmp_addflag=' -nofor_main' ;;
++ lf95*) # Lahey Fortran 8.1
++ _LT_TAGVAR(whole_archive_flag_spec, $1)=
++ tmp_sharedflag='--shared' ;;
++ nagfor*) # NAGFOR 5.3
++ tmp_sharedflag='-Wl,-shared' ;;
++ xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below)
++ tmp_sharedflag='-qmkshrobj'
++ tmp_addflag= ;;
++ nvcc*) # Cuda Compiler Driver 2.2
++ _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
++ _LT_TAGVAR(compiler_needs_object, $1)=yes
++ ;;
++ esac
++ case `$CC -V 2>&1 | $SED 5q` in
++ *Sun\ C*) # Sun C 5.9
++ _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
++ _LT_TAGVAR(compiler_needs_object, $1)=yes
++ tmp_sharedflag='-G' ;;
++ *Sun\ F*) # Sun Fortran 8.3
++ tmp_sharedflag='-G' ;;
++ esac
++ _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
++
++ if test yes = "$supports_anon_versioning"; then
++ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
++ cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
++ echo "local: *; };" >> $output_objdir/$libname.ver~
++ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib'
++ fi
++
++ case $cc_basename in
++ tcc*)
++ _LT_TAGVAR(export_dynamic_flag_spec, $1)='-rdynamic'
++ ;;
++ xlf* | bgf* | bgxlf* | mpixlf*)
++ # IBM XL Fortran 10.1 on PPC cannot create shared libs itself
++ _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive'
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
++ _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib'
++ if test yes = "$supports_anon_versioning"; then
++ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
++ cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
++ echo "local: *; };" >> $output_objdir/$libname.ver~
++ $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib'
++ fi
++ ;;
++ esac
++ else
++ _LT_TAGVAR(ld_shlibs, $1)=no
++ fi
++ ;;
++
++ netbsd*)
++ if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
++ _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
++ wlarc=
++ else
++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
++ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
++ fi
++ ;;
++
++ solaris*)
++ if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then
++ _LT_TAGVAR(ld_shlibs, $1)=no
++ cat <<_LT_EOF 1>&2
++
++*** Warning: The releases 2.8.* of the GNU linker cannot reliably
++*** create shared libraries on Solaris systems. Therefore, libtool
++*** is disabling shared libraries support. We urge you to upgrade GNU
++*** binutils to release 2.9.1 or newer. Another option is to modify
++*** your PATH or compiler configuration so that the native linker is
++*** used, and then restart.
++
++_LT_EOF
++ elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
++ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
++ else
++ _LT_TAGVAR(ld_shlibs, $1)=no
++ fi
++ ;;
++
++ sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
++ case `$LD -v 2>&1` in
++ *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*)
++ _LT_TAGVAR(ld_shlibs, $1)=no
++ cat <<_LT_EOF 1>&2
++
++*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot
++*** reliably create shared libraries on SCO systems. Therefore, libtool
++*** is disabling shared libraries support. We urge you to upgrade GNU
++*** binutils to release 2.16.91.0.3 or newer. Another option is to modify
++*** your PATH or compiler configuration so that the native linker is
++*** used, and then restart.
++
++_LT_EOF
++ ;;
++ *)
++ # For security reasons, it is highly recommended that you always
++ # use absolute paths for naming shared libraries, and exclude the
++ # DT_RUNPATH tag from executables and libraries. But doing so
++ # requires that you compile everything twice, which is a pain.
++ if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
++ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
++ else
++ _LT_TAGVAR(ld_shlibs, $1)=no
++ fi
++ ;;
++ esac
++ ;;
++
++ sunos4*)
++ _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
++ wlarc=
++ _LT_TAGVAR(hardcode_direct, $1)=yes
++ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
++ ;;
++
++ *)
++ if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
++ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
++ else
++ _LT_TAGVAR(ld_shlibs, $1)=no
++ fi
++ ;;
++ esac
++
++ if test no = "$_LT_TAGVAR(ld_shlibs, $1)"; then
++ runpath_var=
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
++ _LT_TAGVAR(export_dynamic_flag_spec, $1)=
++ _LT_TAGVAR(whole_archive_flag_spec, $1)=
++ fi
++ else
++ # PORTME fill in a description of your system's linker (not GNU ld)
++ case $host_os in
++ aix3*)
++ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
++ _LT_TAGVAR(always_export_symbols, $1)=yes
++ _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
++ # Note: this linker hardcodes the directories in LIBPATH if there
++ # are no directories specified by -L.
++ _LT_TAGVAR(hardcode_minus_L, $1)=yes
++ if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then
++ # Neither direct hardcoding nor static linking is supported with a
++ # broken collect2.
++ _LT_TAGVAR(hardcode_direct, $1)=unsupported
++ fi
++ ;;
++
++ aix[[4-9]]*)
++ if test ia64 = "$host_cpu"; then
++ # On IA64, the linker does run time linking by default, so we don't
++ # have to do anything special.
++ aix_use_runtimelinking=no
++ exp_sym_flag='-Bexport'
++ no_entry_flag=
++ else
++ # If we're using GNU nm, then we don't want the "-C" option.
++ # -C means demangle to GNU nm, but means don't demangle to AIX nm.
++ # Without the "-l" option, or with the "-B" option, AIX nm treats
++ # weak defined symbols like other global defined symbols, whereas
++ # GNU nm marks them as "W".
++ # While the 'weak' keyword is ignored in the Export File, we need
++ # it in the Import File for the 'aix-soname' feature, so we have
++ # to replace the "-B" option with "-P" for AIX nm.
++ if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
++ _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols'
++ else
++ _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "L") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols'
++ fi
++ aix_use_runtimelinking=no
++
++ # Test if we are trying to use run time linking or normal
++ # AIX style linking. If -brtl is somewhere in LDFLAGS, we
++ # have runtime linking enabled, and use it for executables.
++ # For shared libraries, we enable/disable runtime linking
++ # depending on the kind of the shared library created -
++ # when "with_aix_soname,aix_use_runtimelinking" is:
++ # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables
++ # "aix,yes" lib.so shared, rtl:yes, for executables
++ # lib.a static archive
++ # "both,no" lib.so.V(shr.o) shared, rtl:yes
++ # lib.a(lib.so.V) shared, rtl:no, for executables
++ # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables
++ # lib.a(lib.so.V) shared, rtl:no
++ # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables
++ # lib.a static archive
++ case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*)
++ for ld_flag in $LDFLAGS; do
++ if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then
++ aix_use_runtimelinking=yes
++ break
++ fi
++ done
++ if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then
++ # With aix-soname=svr4, we create the lib.so.V shared archives only,
++ # so we don't have lib.a shared libs to link our executables.
++ # We have to force runtime linking in this case.
++ aix_use_runtimelinking=yes
++ LDFLAGS="$LDFLAGS -Wl,-brtl"
++ fi
++ ;;
++ esac
++
++ exp_sym_flag='-bexport'
++ no_entry_flag='-bnoentry'
++ fi
++
++ # When large executables or shared objects are built, AIX ld can
++ # have problems creating the table of contents. If linking a library
++ # or program results in "error TOC overflow" add -mminimal-toc to
++ # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
++ # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
++
++ _LT_TAGVAR(archive_cmds, $1)=''
++ _LT_TAGVAR(hardcode_direct, $1)=yes
++ _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
++ _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
++ _LT_TAGVAR(link_all_deplibs, $1)=yes
++ _LT_TAGVAR(file_list_spec, $1)='$wl-f,'
++ case $with_aix_soname,$aix_use_runtimelinking in
++ aix,*) ;; # traditional, no import file
++ svr4,* | *,yes) # use import file
++ # The Import File defines what to hardcode.
++ _LT_TAGVAR(hardcode_direct, $1)=no
++ _LT_TAGVAR(hardcode_direct_absolute, $1)=no
++ ;;
++ esac
++
++ if test yes = "$GCC"; then
++ case $host_os in aix4.[[012]]|aix4.[[012]].*)
++ # We only want to do this on AIX 4.2 and lower, the check
++ # below for broken collect2 doesn't work under 4.3+
++ collect2name=`$CC -print-prog-name=collect2`
++ if test -f "$collect2name" &&
++ strings "$collect2name" | $GREP resolve_lib_name >/dev/null
++ then
++ # We have reworked collect2
++ :
++ else
++ # We have old collect2
++ _LT_TAGVAR(hardcode_direct, $1)=unsupported
++ # It fails to find uninstalled libraries when the uninstalled
++ # path is not listed in the libpath. Setting hardcode_minus_L
++ # to unsupported forces relinking
++ _LT_TAGVAR(hardcode_minus_L, $1)=yes
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
++ _LT_TAGVAR(hardcode_libdir_separator, $1)=
++ fi
++ ;;
++ esac
++ shared_flag='-shared'
++ if test yes = "$aix_use_runtimelinking"; then
++ shared_flag="$shared_flag "'$wl-G'
++ fi
++ # Need to ensure runtime linking is disabled for the traditional
++ # shared library, or the linker may eventually find shared libraries
++ # /with/ Import File - we do not want to mix them.
++ shared_flag_aix='-shared'
++ shared_flag_svr4='-shared $wl-G'
++ else
++ # not using gcc
++ if test ia64 = "$host_cpu"; then
++ # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
++ # chokes on -Wl,-G. The following line is correct:
++ shared_flag='-G'
++ else
++ if test yes = "$aix_use_runtimelinking"; then
++ shared_flag='$wl-G'
++ else
++ shared_flag='$wl-bM:SRE'
++ fi
++ shared_flag_aix='$wl-bM:SRE'
++ shared_flag_svr4='$wl-G'
++ fi
++ fi
++
++ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall'
++ # It seems that -bexpall does not export symbols beginning with
++ # underscore (_), so it is better to generate a list of symbols to export.
++ _LT_TAGVAR(always_export_symbols, $1)=yes
++ if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then
++ # Warning - without using the other runtime loading flags (-brtl),
++ # -berok will link without error, but may produce a broken library.
++ _LT_TAGVAR(allow_undefined_flag, $1)='-berok'
++ # Determine the default libpath from the value encoded in an
++ # empty executable.
++ _LT_SYS_MODULE_PATH_AIX([$1])
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath"
++ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag
++ else
++ if test ia64 = "$host_cpu"; then
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib'
++ _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
++ _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols"
++ else
++ # Determine the default libpath from the value encoded in an
++ # empty executable.
++ _LT_SYS_MODULE_PATH_AIX([$1])
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath"
++ # Warning - without using the other run time loading flags,
++ # -berok will link without error, but may produce a broken library.
++ _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok'
++ _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok'
++ if test yes = "$with_gnu_ld"; then
++ # We only use this code for GNU lds that support --whole-archive.
++ _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive'
++ else
++ # Exported symbols can be pulled into shared objects from archives
++ _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
++ fi
++ _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
++ _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d'
++ # -brtl affects multiple linker settings, -berok does not and is overridden later
++ compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`'
++ if test svr4 != "$with_aix_soname"; then
++ # This is similar to how AIX traditionally builds its shared libraries.
++ _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname'
++ fi
++ if test aix != "$with_aix_soname"; then
++ _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp'
++ else
++ # used by -dlpreopen to get the symbols
++ _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir'
++ fi
++ _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d'
++ fi
++ fi
++ ;;
++
++ amigaos*)
++ case $host_cpu in
++ powerpc)
++ # see comment about AmigaOS4 .so support
++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
++ _LT_TAGVAR(archive_expsym_cmds, $1)=''
++ ;;
++ m68k)
++ _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
++ _LT_TAGVAR(hardcode_minus_L, $1)=yes
++ ;;
++ esac
++ ;;
++
++ bsdi[[45]]*)
++ _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic
++ ;;
++
++ cygwin* | mingw* | pw32* | cegcc*)
++ # When not using gcc, we currently assume that we are using
++ # Microsoft Visual C++ or Intel C++ Compiler.
++ # hardcode_libdir_flag_spec is actually meaningless, as there is
++ # no search path for DLLs.
++ case $cc_basename in
++ cl* | icl*)
++ # Native MSVC or ICC
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
++ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
++ _LT_TAGVAR(always_export_symbols, $1)=yes
++ _LT_TAGVAR(file_list_spec, $1)='@'
++ # Tell ltmain to make .lib files, not .a files.
++ libext=lib
++ # Tell ltmain to make .dll files, not .so files.
++ shrext_cmds=.dll
++ # FIXME: Setting linknames here is a bad hack.
++ _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames='
++ _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then
++ cp "$export_symbols" "$output_objdir/$soname.def";
++ echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp";
++ else
++ $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp;
++ fi~
++ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~
++ linknames='
++ # The linker will not automatically build a static lib if we build a DLL.
++ # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true'
++ _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
++ _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*'
++ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols'
++ # Don't use ranlib
++ _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib'
++ _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~
++ lt_tool_outputfile="@TOOL_OUTPUT@"~
++ case $lt_outputfile in
++ *.exe|*.EXE) ;;
++ *)
++ lt_outputfile=$lt_outputfile.exe
++ lt_tool_outputfile=$lt_tool_outputfile.exe
++ ;;
++ esac~
++ if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then
++ $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1;
++ $RM "$lt_outputfile.manifest";
++ fi'
++ ;;
++ *)
++ # Assume MSVC and ICC wrapper
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
++ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
++ # Tell ltmain to make .lib files, not .a files.
++ libext=lib
++ # Tell ltmain to make .dll files, not .so files.
++ shrext_cmds=.dll
++ # FIXME: Setting linknames here is a bad hack.
++ _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames='
++ # The linker will automatically build a .lib file if we build a DLL.
++ _LT_TAGVAR(old_archive_from_new_cmds, $1)='true'
++ # FIXME: Should let the user specify the lib program.
++ _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs'
++ _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
++ ;;
++ esac
++ ;;
++
++ darwin* | rhapsody*)
++ _LT_DARWIN_LINKER_FEATURES($1)
++ ;;
++
++ dgux*)
++ _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
++ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
++ ;;
++
++ # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
++ # support. Future versions do this automatically, but an explicit c++rt0.o
++ # does not break anything, and helps significantly (at the cost of a little
++ # extra space).
++ freebsd2.2*)
++ _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
++ _LT_TAGVAR(hardcode_direct, $1)=yes
++ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
++ ;;
++
++ # Unfortunately, older versions of FreeBSD 2 do not have this feature.
++ freebsd2.*)
++ _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
++ _LT_TAGVAR(hardcode_direct, $1)=yes
++ _LT_TAGVAR(hardcode_minus_L, $1)=yes
++ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
++ ;;
++
++ # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
++ freebsd* | dragonfly* | midnightbsd*)
++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
++ _LT_TAGVAR(hardcode_direct, $1)=yes
++ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
++ ;;
++
++ hpux9*)
++ if test yes = "$GCC"; then
++ _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
++ else
++ _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
++ fi
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir'
++ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
++ _LT_TAGVAR(hardcode_direct, $1)=yes
++
++ # hardcode_minus_L: Not really in the search PATH,
++ # but as the default location of the library.
++ _LT_TAGVAR(hardcode_minus_L, $1)=yes
++ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
++ ;;
++
++ hpux10*)
++ if test yes,no = "$GCC,$with_gnu_ld"; then
++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
++ else
++ _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
++ fi
++ if test no = "$with_gnu_ld"; then
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir'
++ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
++ _LT_TAGVAR(hardcode_direct, $1)=yes
++ _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
++ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
++ # hardcode_minus_L: Not really in the search PATH,
++ # but as the default location of the library.
++ _LT_TAGVAR(hardcode_minus_L, $1)=yes
++ fi
++ ;;
++
++ hpux11*)
++ if test yes,no = "$GCC,$with_gnu_ld"; then
++ case $host_cpu in
++ hppa*64*)
++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags'
++ ;;
++ ia64*)
++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
++ ;;
++ *)
++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
++ ;;
++ esac
++ else
++ case $host_cpu in
++ hppa*64*)
++ _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags'
++ ;;
++ ia64*)
++ _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
++ ;;
++ *)
++ m4_if($1, [], [
++ # Older versions of the 11.00 compiler do not understand -b yet
++ # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does)
++ _LT_LINKER_OPTION([if $CC understands -b],
++ _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b],
++ [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'],
++ [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])],
++ [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'])
++ ;;
++ esac
++ fi
++ if test no = "$with_gnu_ld"; then
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir'
++ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
++
++ case $host_cpu in
++ hppa*64*|ia64*)
++ _LT_TAGVAR(hardcode_direct, $1)=no
++ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
++ ;;
++ *)
++ _LT_TAGVAR(hardcode_direct, $1)=yes
++ _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
++ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
++
++ # hardcode_minus_L: Not really in the search PATH,
++ # but as the default location of the library.
++ _LT_TAGVAR(hardcode_minus_L, $1)=yes
++ ;;
++ esac
++ fi
++ ;;
++
++ irix5* | irix6* | nonstopux*)
++ if test yes = "$GCC"; then
++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
++ # Try to use the -exported_symbol ld option, if it does not
++ # work, assume that -exports_file does not work either and
++ # implicitly export all symbols.
++ # This should be the same for all languages, so no per-tag cache variable.
++ AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol],
++ [lt_cv_irix_exported_symbol],
++ [save_LDFLAGS=$LDFLAGS
++ LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null"
++ AC_LINK_IFELSE(
++ [AC_LANG_SOURCE(
++ [AC_LANG_CASE([C], [[int foo (void) { return 0; }]],
++ [C++], [[int foo (void) { return 0; }]],
++ [Fortran 77], [[
++ subroutine foo
++ end]],
++ [Fortran], [[
++ subroutine foo
++ end]])])],
++ [lt_cv_irix_exported_symbol=yes],
++ [lt_cv_irix_exported_symbol=no])
++ LDFLAGS=$save_LDFLAGS])
++ if test yes = "$lt_cv_irix_exported_symbol"; then
++ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib'
++ fi
++ else
++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
++ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib'
++ fi
++ _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
++ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
++ _LT_TAGVAR(inherit_rpath, $1)=yes
++ _LT_TAGVAR(link_all_deplibs, $1)=yes
++ ;;
++
++ linux*)
++ case $cc_basename in
++ tcc*)
++ # Fabrice Bellard et al's Tiny C Compiler
++ _LT_TAGVAR(ld_shlibs, $1)=yes
++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
++ ;;
++ esac
++ ;;
++
++ netbsd*)
++ if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
++ _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out
++ else
++ _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF
++ fi
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
++ _LT_TAGVAR(hardcode_direct, $1)=yes
++ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
++ ;;
++
++ newsos6)
++ _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
++ _LT_TAGVAR(hardcode_direct, $1)=yes
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
++ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
++ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
++ ;;
++
++ *nto* | *qnx*)
++ ;;
++
++ openbsd* | bitrig*)
++ if test -f /usr/libexec/ld.so; then
++ _LT_TAGVAR(hardcode_direct, $1)=yes
++ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
++ _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
++ if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
++ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols'
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
++ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
++ else
++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
++ fi
++ else
++ _LT_TAGVAR(ld_shlibs, $1)=no
++ fi
++ ;;
++
++ os2*)
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
++ _LT_TAGVAR(hardcode_minus_L, $1)=yes
++ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
++ shrext_cmds=.dll
++ _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
++ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
++ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
++ $ECHO EXPORTS >> $output_objdir/$libname.def~
++ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~
++ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
++ emximp -o $lib $output_objdir/$libname.def'
++ _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
++ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
++ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
++ $ECHO EXPORTS >> $output_objdir/$libname.def~
++ prefix_cmds="$SED"~
++ if test EXPORTS = "`$SED 1q $export_symbols`"; then
++ prefix_cmds="$prefix_cmds -e 1d";
++ fi~
++ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~
++ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~
++ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
++ emximp -o $lib $output_objdir/$libname.def'
++ _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
++ _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
++ _LT_TAGVAR(file_list_spec, $1)='@'
++ ;;
++
++ osf3*)
++ if test yes = "$GCC"; then
++ _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*'
++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
++ else
++ _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
++ fi
++ _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
++ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
++ ;;
++
++ osf4* | osf5*) # as osf3* with the addition of -msym flag
++ if test yes = "$GCC"; then
++ _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*'
++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
++ else
++ _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
++ _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~
++ $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp'
++
++ # Both c and cxx compiler support -rpath directly
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
++ fi
++ _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
++ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
++ ;;
++
++ solaris*)
++ _LT_TAGVAR(no_undefined_flag, $1)=' -z defs'
++ if test yes = "$GCC"; then
++ wlarc='$wl'
++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags'
++ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
++ $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
++ else
++ case `$CC -V 2>&1` in
++ *"Compilers 5.0"*)
++ wlarc=''
++ _LT_TAGVAR(archive_cmds, $1)='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags'
++ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
++ $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp'
++ ;;
++ *)
++ wlarc='$wl'
++ _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags'
++ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
++ $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
++ ;;
++ esac
++ fi
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
++ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
++ case $host_os in
++ solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
++ *)
++ # The compiler driver will combine and reorder linker options,
++ # but understands '-z linker_flag'. GCC discards it without '$wl',
++ # but is careful enough not to reorder.
++ # Supported since Solaris 2.6 (maybe 2.5.1?)
++ if test yes = "$GCC"; then
++ _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract'
++ else
++ _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract'
++ fi
++ ;;
++ esac
++ _LT_TAGVAR(link_all_deplibs, $1)=yes
++ ;;
++
++ sunos4*)
++ if test sequent = "$host_vendor"; then
++ # Use $CC to link under sequent, because it throws in some extra .o
++ # files that make .init and .fini sections work.
++ _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags'
++ else
++ _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
++ fi
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
++ _LT_TAGVAR(hardcode_direct, $1)=yes
++ _LT_TAGVAR(hardcode_minus_L, $1)=yes
++ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
++ ;;
++
++ sysv4)
++ case $host_vendor in
++ sni)
++ _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
++ _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true???
++ ;;
++ siemens)
++ ## LD is ld it makes a PLAMLIB
++ ## CC just makes a GrossModule.
++ _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags'
++ _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs'
++ _LT_TAGVAR(hardcode_direct, $1)=no
++ ;;
++ motorola)
++ _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
++ _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie
++ ;;
++ esac
++ runpath_var='LD_RUN_PATH'
++ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
++ ;;
++
++ sysv4.3*)
++ _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
++ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
++ _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport'
++ ;;
++
++ sysv4*MP*)
++ if test -d /usr/nec; then
++ _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
++ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
++ runpath_var=LD_RUN_PATH
++ hardcode_runpath_var=yes
++ _LT_TAGVAR(ld_shlibs, $1)=yes
++ fi
++ ;;
++
++ sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*)
++ _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text'
++ _LT_TAGVAR(archive_cmds_need_lc, $1)=no
++ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
++ runpath_var='LD_RUN_PATH'
++
++ if test yes = "$GCC"; then
++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++ else
++ _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++ fi
++ ;;
++
++ sysv5* | sco3.2v5* | sco5v6*)
++ # Note: We CANNOT use -z defs as we might desire, because we do not
++ # link with -lc, and that would cause any symbols used from libc to
++ # always be unresolved, which means just about no library would
++ # ever link correctly. If we're not using GNU ld we use -z text
++ # though, which does catch some bad symbols but isn't as heavy-handed
++ # as -z defs.
++ _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text'
++ _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs'
++ _LT_TAGVAR(archive_cmds_need_lc, $1)=no
++ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir'
++ _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
++ _LT_TAGVAR(link_all_deplibs, $1)=yes
++ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport'
++ runpath_var='LD_RUN_PATH'
++
++ if test yes = "$GCC"; then
++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++ else
++ _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++ fi
++ ;;
++
++ uts4*)
++ _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
++ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
++ ;;
++
++ *)
++ _LT_TAGVAR(ld_shlibs, $1)=no
++ ;;
++ esac
++
++ if test sni = "$host_vendor"; then
++ case $host in
++ sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
++ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Blargedynsym'
++ ;;
++ esac
++ fi
++ fi
++])
++AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)])
++test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no
++
++_LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld
++
++_LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl
++_LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl
++_LT_DECL([], [extract_expsyms_cmds], [2],
++ [The commands to extract the exported symbol list from a shared archive])
++
++#
++# Do we need to explicitly link libc?
++#
++case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in
++x|xyes)
++ # Assume -lc should be added
++ _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
++
++ if test yes,yes = "$GCC,$enable_shared"; then
++ case $_LT_TAGVAR(archive_cmds, $1) in
++ *'~'*)
++ # FIXME: we may have to deal with multi-command sequences.
++ ;;
++ '$CC '*)
++ # Test whether the compiler implicitly links with -lc since on some
++ # systems, -lgcc has to come before -lc. If gcc already passes -lc
++ # to ld, don't add -lc before -lgcc.
++ AC_CACHE_CHECK([whether -lc should be explicitly linked in],
++ [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1),
++ [$RM conftest*
++ echo "$lt_simple_compile_test_code" > conftest.$ac_ext
++
++ if AC_TRY_EVAL(ac_compile) 2>conftest.err; then
++ soname=conftest
++ lib=conftest
++ libobjs=conftest.$ac_objext
++ deplibs=
++ wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1)
++ pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1)
++ compiler_flags=-v
++ linker_flags=-v
++ verstring=
++ output_objdir=.
++ libname=conftest
++ lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1)
++ _LT_TAGVAR(allow_undefined_flag, $1)=
++ if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1)
++ then
++ lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no
++ else
++ lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes
++ fi
++ _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag
++ else
++ cat conftest.err 1>&5
++ fi
++ $RM conftest*
++ ])
++ _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)
++ ;;
++ esac
++ fi
++ ;;
++esac
++
++_LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0],
++ [Whether or not to add -lc for building shared libraries])
++_LT_TAGDECL([allow_libtool_libs_with_static_runtimes],
++ [enable_shared_with_static_runtimes], [0],
++ [Whether or not to disallow shared libs when runtime libs are static])
++_LT_TAGDECL([], [export_dynamic_flag_spec], [1],
++ [Compiler flag to allow reflexive dlopens])
++_LT_TAGDECL([], [whole_archive_flag_spec], [1],
++ [Compiler flag to generate shared objects directly from archives])
++_LT_TAGDECL([], [compiler_needs_object], [1],
++ [Whether the compiler copes with passing no objects directly])
++_LT_TAGDECL([], [old_archive_from_new_cmds], [2],
++ [Create an old-style archive from a shared archive])
++_LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2],
++ [Create a temporary old-style archive to link instead of a shared archive])
++_LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive])
++_LT_TAGDECL([], [archive_expsym_cmds], [2])
++_LT_TAGDECL([], [module_cmds], [2],
++ [Commands used to build a loadable module if different from building
++ a shared archive.])
++_LT_TAGDECL([], [module_expsym_cmds], [2])
++_LT_TAGDECL([], [with_gnu_ld], [1],
++ [Whether we are building with GNU ld or not])
++_LT_TAGDECL([], [allow_undefined_flag], [1],
++ [Flag that allows shared libraries with undefined symbols to be built])
++_LT_TAGDECL([], [no_undefined_flag], [1],
++ [Flag that enforces no undefined symbols])
++_LT_TAGDECL([], [hardcode_libdir_flag_spec], [1],
++ [Flag to hardcode $libdir into a binary during linking.
++ This must work even if $libdir does not exist])
++_LT_TAGDECL([], [hardcode_libdir_separator], [1],
++ [Whether we need a single "-rpath" flag with a separated argument])
++_LT_TAGDECL([], [hardcode_direct], [0],
++ [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes
++ DIR into the resulting binary])
++_LT_TAGDECL([], [hardcode_direct_absolute], [0],
++ [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes
++ DIR into the resulting binary and the resulting library dependency is
++ "absolute", i.e impossible to change by setting $shlibpath_var if the
++ library is relocated])
++_LT_TAGDECL([], [hardcode_minus_L], [0],
++ [Set to "yes" if using the -LDIR flag during linking hardcodes DIR
++ into the resulting binary])
++_LT_TAGDECL([], [hardcode_shlibpath_var], [0],
++ [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR
++ into the resulting binary])
++_LT_TAGDECL([], [hardcode_automatic], [0],
++ [Set to "yes" if building a shared library automatically hardcodes DIR
++ into the library and all subsequent libraries and executables linked
++ against it])
++_LT_TAGDECL([], [inherit_rpath], [0],
++ [Set to yes if linker adds runtime paths of dependent libraries
++ to runtime path list])
++_LT_TAGDECL([], [link_all_deplibs], [0],
++ [Whether libtool must link a program against all its dependency libraries])
++_LT_TAGDECL([], [always_export_symbols], [0],
++ [Set to "yes" if exported symbols are required])
++_LT_TAGDECL([], [export_symbols_cmds], [2],
++ [The commands to list exported symbols])
++_LT_TAGDECL([], [exclude_expsyms], [1],
++ [Symbols that should not be listed in the preloaded symbols])
++_LT_TAGDECL([], [include_expsyms], [1],
++ [Symbols that must always be exported])
++_LT_TAGDECL([], [prelink_cmds], [2],
++ [Commands necessary for linking programs (against libraries) with templates])
++_LT_TAGDECL([], [postlink_cmds], [2],
++ [Commands necessary for finishing linking programs])
++_LT_TAGDECL([], [file_list_spec], [1],
++ [Specify filename containing input files])
++dnl FIXME: Not yet implemented
++dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1],
++dnl [Compiler flag to generate thread safe objects])
++])# _LT_LINKER_SHLIBS
++
++
++# _LT_LANG_C_CONFIG([TAG])
++# ------------------------
++# Ensure that the configuration variables for a C compiler are suitably
++# defined. These variables are subsequently used by _LT_CONFIG to write
++# the compiler configuration to 'libtool'.
++m4_defun([_LT_LANG_C_CONFIG],
++[m4_require([_LT_DECL_EGREP])dnl
++lt_save_CC=$CC
++AC_LANG_PUSH(C)
++
++# Source file extension for C test sources.
++ac_ext=c
++
++# Object file extension for compiled C test sources.
++objext=o
++_LT_TAGVAR(objext, $1)=$objext
++
++# Code to be used in simple compile tests
++lt_simple_compile_test_code="int some_variable = 0;"
++
++# Code to be used in simple link tests
++lt_simple_link_test_code='int main(){return(0);}'
++
++_LT_TAG_COMPILER
++# Save the default compiler, since it gets overwritten when the other
++# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP.
++compiler_DEFAULT=$CC
++
++# save warnings/boilerplate of simple test code
++_LT_COMPILER_BOILERPLATE
++_LT_LINKER_BOILERPLATE
++
++if test -n "$compiler"; then
++ _LT_COMPILER_NO_RTTI($1)
++ _LT_COMPILER_PIC($1)
++ _LT_COMPILER_C_O($1)
++ _LT_COMPILER_FILE_LOCKS($1)
++ _LT_LINKER_SHLIBS($1)
++ _LT_SYS_DYNAMIC_LINKER($1)
++ _LT_LINKER_HARDCODE_LIBPATH($1)
++ LT_SYS_DLOPEN_SELF
++ _LT_CMD_STRIPLIB
++
++ # Report what library types will actually be built
++ AC_MSG_CHECKING([if libtool supports shared libraries])
++ AC_MSG_RESULT([$can_build_shared])
++
++ AC_MSG_CHECKING([whether to build shared libraries])
++ test no = "$can_build_shared" && enable_shared=no
++
++ # On AIX, shared libraries and static libraries use the same namespace, and
++ # are all built from PIC.
++ case $host_os in
++ aix3*)
++ test yes = "$enable_shared" && enable_static=no
++ if test -n "$RANLIB"; then
++ archive_cmds="$archive_cmds~\$RANLIB \$lib"
++ postinstall_cmds='$RANLIB $lib'
++ fi
++ ;;
++
++ aix[[4-9]]*)
++ if test ia64 != "$host_cpu"; then
++ case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in
++ yes,aix,yes) ;; # shared object as lib.so file only
++ yes,svr4,*) ;; # shared object as lib.so archive member only
++ yes,*) enable_static=no ;; # shared object in lib.a archive as well
++ esac
++ fi
++ ;;
++ esac
++ AC_MSG_RESULT([$enable_shared])
++
++ AC_MSG_CHECKING([whether to build static libraries])
++ # Make sure either enable_shared or enable_static is yes.
++ test yes = "$enable_shared" || enable_static=yes
++ AC_MSG_RESULT([$enable_static])
++
++ _LT_CONFIG($1)
++fi
++AC_LANG_POP
++CC=$lt_save_CC
++])# _LT_LANG_C_CONFIG
++
++
++# _LT_LANG_CXX_CONFIG([TAG])
++# --------------------------
++# Ensure that the configuration variables for a C++ compiler are suitably
++# defined. These variables are subsequently used by _LT_CONFIG to write
++# the compiler configuration to 'libtool'.
++m4_defun([_LT_LANG_CXX_CONFIG],
++[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
++m4_require([_LT_DECL_EGREP])dnl
++m4_require([_LT_PATH_MANIFEST_TOOL])dnl
++if test -n "$CXX" && ( test no != "$CXX" &&
++ ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) ||
++ (test g++ != "$CXX"))); then
++ AC_PROG_CXXCPP
++else
++ _lt_caught_CXX_error=yes
++fi
++
++AC_LANG_PUSH(C++)
++_LT_TAGVAR(archive_cmds_need_lc, $1)=no
++_LT_TAGVAR(allow_undefined_flag, $1)=
++_LT_TAGVAR(always_export_symbols, $1)=no
++_LT_TAGVAR(archive_expsym_cmds, $1)=
++_LT_TAGVAR(compiler_needs_object, $1)=no
++_LT_TAGVAR(export_dynamic_flag_spec, $1)=
++_LT_TAGVAR(hardcode_direct, $1)=no
++_LT_TAGVAR(hardcode_direct_absolute, $1)=no
++_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
++_LT_TAGVAR(hardcode_libdir_separator, $1)=
++_LT_TAGVAR(hardcode_minus_L, $1)=no
++_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
++_LT_TAGVAR(hardcode_automatic, $1)=no
++_LT_TAGVAR(inherit_rpath, $1)=no
++_LT_TAGVAR(module_cmds, $1)=
++_LT_TAGVAR(module_expsym_cmds, $1)=
++_LT_TAGVAR(link_all_deplibs, $1)=unknown
++_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
++_LT_TAGVAR(reload_flag, $1)=$reload_flag
++_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
++_LT_TAGVAR(no_undefined_flag, $1)=
++_LT_TAGVAR(whole_archive_flag_spec, $1)=
++_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
++
++# Source file extension for C++ test sources.
++ac_ext=cpp
++
++# Object file extension for compiled C++ test sources.
++objext=o
++_LT_TAGVAR(objext, $1)=$objext
++
++# No sense in running all these tests if we already determined that
++# the CXX compiler isn't working. Some variables (like enable_shared)
++# are currently assumed to apply to all compilers on this platform,
++# and will be corrupted by setting them based on a non-working compiler.
++if test yes != "$_lt_caught_CXX_error"; then
++ # Code to be used in simple compile tests
++ lt_simple_compile_test_code="int some_variable = 0;"
++
++ # Code to be used in simple link tests
++ lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }'
++
++ # ltmain only uses $CC for tagged configurations so make sure $CC is set.
++ _LT_TAG_COMPILER
++
++ # save warnings/boilerplate of simple test code
++ _LT_COMPILER_BOILERPLATE
++ _LT_LINKER_BOILERPLATE
++
++ # Allow CC to be a program name with arguments.
++ lt_save_CC=$CC
++ lt_save_CFLAGS=$CFLAGS
++ lt_save_LD=$LD
++ lt_save_GCC=$GCC
++ GCC=$GXX
++ lt_save_with_gnu_ld=$with_gnu_ld
++ lt_save_path_LD=$lt_cv_path_LD
++ if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then
++ lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx
++ else
++ $as_unset lt_cv_prog_gnu_ld
++ fi
++ if test -n "${lt_cv_path_LDCXX+set}"; then
++ lt_cv_path_LD=$lt_cv_path_LDCXX
++ else
++ $as_unset lt_cv_path_LD
++ fi
++ test -z "${LDCXX+set}" || LD=$LDCXX
++ CC=${CXX-"c++"}
++ CFLAGS=$CXXFLAGS
++ compiler=$CC
++ _LT_TAGVAR(compiler, $1)=$CC
++ _LT_CC_BASENAME([$compiler])
++
++ if test -n "$compiler"; then
++ # We don't want -fno-exception when compiling C++ code, so set the
++ # no_builtin_flag separately
++ if test yes = "$GXX"; then
++ _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin'
++ else
++ _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
++ fi
++
++ if test yes = "$GXX"; then
++ # Set up default GNU C++ configuration
++
++ LT_PATH_LD
++
++ # Check if GNU C++ uses GNU ld as the underlying linker, since the
++ # archiving commands below assume that GNU ld is being used.
++ if test yes = "$with_gnu_ld"; then
++ _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
++ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
++
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
++ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
++
++ # If archive_cmds runs LD, not CC, wlarc should be empty
++ # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to
++ # investigate it a little bit more. (MM)
++ wlarc='$wl'
++
++ # ancient GNU ld didn't support --whole-archive et. al.
++ if eval "`$CC -print-prog-name=ld` --help 2>&1" |
++ $GREP 'no-whole-archive' > /dev/null; then
++ _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive'
++ else
++ _LT_TAGVAR(whole_archive_flag_spec, $1)=
++ fi
++ else
++ with_gnu_ld=no
++ wlarc=
++
++ # A generic and very simple default shared library creation
++ # command for GNU C++ for the case where it uses the native
++ # linker, instead of GNU ld. If possible, this setting should
++ # overridden to take advantage of the native linker features on
++ # the platform it is being used on.
++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
++ fi
++
++ # Commands to make compiler produce verbose output that lists
++ # what "hidden" libraries, object files and flags are used when
++ # linking a shared library.
++ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
++
++ else
++ GXX=no
++ with_gnu_ld=no
++ wlarc=
++ fi
++
++ # PORTME: fill in a description of your system's C++ link characteristics
++ AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
++ _LT_TAGVAR(ld_shlibs, $1)=yes
++ case $host_os in
++ aix3*)
++ # FIXME: insert proper C++ library support
++ _LT_TAGVAR(ld_shlibs, $1)=no
++ ;;
++ aix[[4-9]]*)
++ if test ia64 = "$host_cpu"; then
++ # On IA64, the linker does run time linking by default, so we don't
++ # have to do anything special.
++ aix_use_runtimelinking=no
++ exp_sym_flag='-Bexport'
++ no_entry_flag=
++ else
++ aix_use_runtimelinking=no
++
++ # Test if we are trying to use run time linking or normal
++ # AIX style linking. If -brtl is somewhere in LDFLAGS, we
++ # have runtime linking enabled, and use it for executables.
++ # For shared libraries, we enable/disable runtime linking
++ # depending on the kind of the shared library created -
++ # when "with_aix_soname,aix_use_runtimelinking" is:
++ # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables
++ # "aix,yes" lib.so shared, rtl:yes, for executables
++ # lib.a static archive
++ # "both,no" lib.so.V(shr.o) shared, rtl:yes
++ # lib.a(lib.so.V) shared, rtl:no, for executables
++ # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables
++ # lib.a(lib.so.V) shared, rtl:no
++ # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables
++ # lib.a static archive
++ case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*)
++ for ld_flag in $LDFLAGS; do
++ case $ld_flag in
++ *-brtl*)
++ aix_use_runtimelinking=yes
++ break
++ ;;
++ esac
++ done
++ if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then
++ # With aix-soname=svr4, we create the lib.so.V shared archives only,
++ # so we don't have lib.a shared libs to link our executables.
++ # We have to force runtime linking in this case.
++ aix_use_runtimelinking=yes
++ LDFLAGS="$LDFLAGS -Wl,-brtl"
++ fi
++ ;;
++ esac
++
++ exp_sym_flag='-bexport'
++ no_entry_flag='-bnoentry'
++ fi
++
++ # When large executables or shared objects are built, AIX ld can
++ # have problems creating the table of contents. If linking a library
++ # or program results in "error TOC overflow" add -mminimal-toc to
++ # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
++ # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
++
++ _LT_TAGVAR(archive_cmds, $1)=''
++ _LT_TAGVAR(hardcode_direct, $1)=yes
++ _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
++ _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
++ _LT_TAGVAR(link_all_deplibs, $1)=yes
++ _LT_TAGVAR(file_list_spec, $1)='$wl-f,'
++ case $with_aix_soname,$aix_use_runtimelinking in
++ aix,*) ;; # no import file
++ svr4,* | *,yes) # use import file
++ # The Import File defines what to hardcode.
++ _LT_TAGVAR(hardcode_direct, $1)=no
++ _LT_TAGVAR(hardcode_direct_absolute, $1)=no
++ ;;
++ esac
++
++ if test yes = "$GXX"; then
++ case $host_os in aix4.[[012]]|aix4.[[012]].*)
++ # We only want to do this on AIX 4.2 and lower, the check
++ # below for broken collect2 doesn't work under 4.3+
++ collect2name=`$CC -print-prog-name=collect2`
++ if test -f "$collect2name" &&
++ strings "$collect2name" | $GREP resolve_lib_name >/dev/null
++ then
++ # We have reworked collect2
++ :
++ else
++ # We have old collect2
++ _LT_TAGVAR(hardcode_direct, $1)=unsupported
++ # It fails to find uninstalled libraries when the uninstalled
++ # path is not listed in the libpath. Setting hardcode_minus_L
++ # to unsupported forces relinking
++ _LT_TAGVAR(hardcode_minus_L, $1)=yes
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
++ _LT_TAGVAR(hardcode_libdir_separator, $1)=
++ fi
++ esac
++ shared_flag='-shared'
++ if test yes = "$aix_use_runtimelinking"; then
++ shared_flag=$shared_flag' $wl-G'
++ fi
++ # Need to ensure runtime linking is disabled for the traditional
++ # shared library, or the linker may eventually find shared libraries
++ # /with/ Import File - we do not want to mix them.
++ shared_flag_aix='-shared'
++ shared_flag_svr4='-shared $wl-G'
++ else
++ # not using gcc
++ if test ia64 = "$host_cpu"; then
++ # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
++ # chokes on -Wl,-G. The following line is correct:
++ shared_flag='-G'
++ else
++ if test yes = "$aix_use_runtimelinking"; then
++ shared_flag='$wl-G'
++ else
++ shared_flag='$wl-bM:SRE'
++ fi
++ shared_flag_aix='$wl-bM:SRE'
++ shared_flag_svr4='$wl-G'
++ fi
++ fi
++
++ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall'
++ # It seems that -bexpall does not export symbols beginning with
++ # underscore (_), so it is better to generate a list of symbols to
++ # export.
++ _LT_TAGVAR(always_export_symbols, $1)=yes
++ if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then
++ # Warning - without using the other runtime loading flags (-brtl),
++ # -berok will link without error, but may produce a broken library.
++ # The "-G" linker flag allows undefined symbols.
++ _LT_TAGVAR(no_undefined_flag, $1)='-bernotok'
++ # Determine the default libpath from the value encoded in an empty
++ # executable.
++ _LT_SYS_MODULE_PATH_AIX([$1])
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath"
++
++ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag
++ else
++ if test ia64 = "$host_cpu"; then
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib'
++ _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
++ _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols"
++ else
++ # Determine the default libpath from the value encoded in an
++ # empty executable.
++ _LT_SYS_MODULE_PATH_AIX([$1])
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath"
++ # Warning - without using the other run time loading flags,
++ # -berok will link without error, but may produce a broken library.
++ _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok'
++ _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok'
++ if test yes = "$with_gnu_ld"; then
++ # We only use this code for GNU lds that support --whole-archive.
++ _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive'
++ else
++ # Exported symbols can be pulled into shared objects from archives
++ _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
++ fi
++ _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
++ _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d'
++ # -brtl affects multiple linker settings, -berok does not and is overridden later
++ compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`'
++ if test svr4 != "$with_aix_soname"; then
++ # This is similar to how AIX traditionally builds its shared
++ # libraries. Need -bnortl late, we may have -brtl in LDFLAGS.
++ _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname'
++ fi
++ if test aix != "$with_aix_soname"; then
++ _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp'
++ else
++ # used by -dlpreopen to get the symbols
++ _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir'
++ fi
++ _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d'
++ fi
++ fi
++ ;;
++
++ beos*)
++ if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
++ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
++ # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
++ # support --undefined. This deserves some investigation. FIXME
++ _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
++ else
++ _LT_TAGVAR(ld_shlibs, $1)=no
++ fi
++ ;;
++
++ chorus*)
++ case $cc_basename in
++ *)
++ # FIXME: insert proper C++ library support
++ _LT_TAGVAR(ld_shlibs, $1)=no
++ ;;
++ esac
++ ;;
++
++ cygwin* | mingw* | pw32* | cegcc*)
++ case $GXX,$cc_basename in
++ ,cl* | no,cl* | ,icl* | no,icl*)
++ # Native MSVC or ICC
++ # hardcode_libdir_flag_spec is actually meaningless, as there is
++ # no search path for DLLs.
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
++ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
++ _LT_TAGVAR(always_export_symbols, $1)=yes
++ _LT_TAGVAR(file_list_spec, $1)='@'
++ # Tell ltmain to make .lib files, not .a files.
++ libext=lib
++ # Tell ltmain to make .dll files, not .so files.
++ shrext_cmds=.dll
++ # FIXME: Setting linknames here is a bad hack.
++ _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames='
++ _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then
++ cp "$export_symbols" "$output_objdir/$soname.def";
++ echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp";
++ else
++ $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp;
++ fi~
++ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~
++ linknames='
++ # The linker will not automatically build a static lib if we build a DLL.
++ # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true'
++ _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
++ # Don't use ranlib
++ _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib'
++ _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~
++ lt_tool_outputfile="@TOOL_OUTPUT@"~
++ case $lt_outputfile in
++ *.exe|*.EXE) ;;
++ *)
++ lt_outputfile=$lt_outputfile.exe
++ lt_tool_outputfile=$lt_tool_outputfile.exe
++ ;;
++ esac~
++ func_to_tool_file "$lt_outputfile"~
++ if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then
++ $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1;
++ $RM "$lt_outputfile.manifest";
++ fi'
++ ;;
++ *)
++ # g++
++ # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
++ # as there is no search path for DLLs.
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
++ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols'
++ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
++ _LT_TAGVAR(always_export_symbols, $1)=no
++ _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
++
++ if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
++ # If the export-symbols file already is a .def file, use it as
++ # is; otherwise, prepend EXPORTS...
++ _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then
++ cp $export_symbols $output_objdir/$soname.def;
++ else
++ echo EXPORTS > $output_objdir/$soname.def;
++ cat $export_symbols >> $output_objdir/$soname.def;
++ fi~
++ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
++ else
++ _LT_TAGVAR(ld_shlibs, $1)=no
++ fi
++ ;;
++ esac
++ ;;
++ darwin* | rhapsody*)
++ _LT_DARWIN_LINKER_FEATURES($1)
++ ;;
++
++ os2*)
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
++ _LT_TAGVAR(hardcode_minus_L, $1)=yes
++ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
++ shrext_cmds=.dll
++ _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
++ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
++ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
++ $ECHO EXPORTS >> $output_objdir/$libname.def~
++ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~
++ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
++ emximp -o $lib $output_objdir/$libname.def'
++ _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
++ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
++ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
++ $ECHO EXPORTS >> $output_objdir/$libname.def~
++ prefix_cmds="$SED"~
++ if test EXPORTS = "`$SED 1q $export_symbols`"; then
++ prefix_cmds="$prefix_cmds -e 1d";
++ fi~
++ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~
++ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~
++ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
++ emximp -o $lib $output_objdir/$libname.def'
++ _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
++ _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
++ _LT_TAGVAR(file_list_spec, $1)='@'
++ ;;
++
++ dgux*)
++ case $cc_basename in
++ ec++*)
++ # FIXME: insert proper C++ library support
++ _LT_TAGVAR(ld_shlibs, $1)=no
++ ;;
++ ghcx*)
++ # Green Hills C++ Compiler
++ # FIXME: insert proper C++ library support
++ _LT_TAGVAR(ld_shlibs, $1)=no
++ ;;
++ *)
++ # FIXME: insert proper C++ library support
++ _LT_TAGVAR(ld_shlibs, $1)=no
++ ;;
++ esac
++ ;;
++
++ freebsd2.*)
++ # C++ shared libraries reported to be fairly broken before
++ # switch to ELF
++ _LT_TAGVAR(ld_shlibs, $1)=no
++ ;;
++
++ freebsd-elf*)
++ _LT_TAGVAR(archive_cmds_need_lc, $1)=no
++ ;;
++
++ freebsd* | dragonfly* | midnightbsd*)
++ # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF
++ # conventions
++ _LT_TAGVAR(ld_shlibs, $1)=yes
++ ;;
++
++ haiku*)
++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
++ _LT_TAGVAR(link_all_deplibs, $1)=yes
++ ;;
++
++ hpux9*)
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir'
++ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
++ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
++ _LT_TAGVAR(hardcode_direct, $1)=yes
++ _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
++ # but as the default
++ # location of the library.
++
++ case $cc_basename in
++ CC*)
++ # FIXME: insert proper C++ library support
++ _LT_TAGVAR(ld_shlibs, $1)=no
++ ;;
++ aCC*)
++ _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
++ # Commands to make compiler produce verbose output that lists
++ # what "hidden" libraries, object files and flags are used when
++ # linking a shared library.
++ #
++ # There doesn't appear to be a way to prevent this compiler from
++ # explicitly linking system object files so we need to strip them
++ # from the output so that they don't get included in the library
++ # dependencies.
++ output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
++ ;;
++ *)
++ if test yes = "$GXX"; then
++ _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
++ else
++ # FIXME: insert proper C++ library support
++ _LT_TAGVAR(ld_shlibs, $1)=no
++ fi
++ ;;
++ esac
++ ;;
++
++ hpux10*|hpux11*)
++ if test no = "$with_gnu_ld"; then
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir'
++ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
++
++ case $host_cpu in
++ hppa*64*|ia64*)
++ ;;
++ *)
++ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
++ ;;
++ esac
++ fi
++ case $host_cpu in
++ hppa*64*|ia64*)
++ _LT_TAGVAR(hardcode_direct, $1)=no
++ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
++ ;;
++ *)
++ _LT_TAGVAR(hardcode_direct, $1)=yes
++ _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
++ _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
++ # but as the default
++ # location of the library.
++ ;;
++ esac
++
++ case $cc_basename in
++ CC*)
++ # FIXME: insert proper C++ library support
++ _LT_TAGVAR(ld_shlibs, $1)=no
++ ;;
++ aCC*)
++ case $host_cpu in
++ hppa*64*)
++ _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
++ ;;
++ ia64*)
++ _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
++ ;;
++ *)
++ _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
++ ;;
++ esac
++ # Commands to make compiler produce verbose output that lists
++ # what "hidden" libraries, object files and flags are used when
++ # linking a shared library.
++ #
++ # There doesn't appear to be a way to prevent this compiler from
++ # explicitly linking system object files so we need to strip them
++ # from the output so that they don't get included in the library
++ # dependencies.
++ output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
++ ;;
++ *)
++ if test yes = "$GXX"; then
++ if test no = "$with_gnu_ld"; then
++ case $host_cpu in
++ hppa*64*)
++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
++ ;;
++ ia64*)
++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
++ ;;
++ *)
++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
++ ;;
++ esac
++ fi
++ else
++ # FIXME: insert proper C++ library support
++ _LT_TAGVAR(ld_shlibs, $1)=no
++ fi
++ ;;
++ esac
++ ;;
++
++ interix[[3-9]]*)
++ _LT_TAGVAR(hardcode_direct, $1)=no
++ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
++ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
++ # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
++ # Instead, shared libraries are loaded at an image base (0x10000000 by
++ # default) and relocated if they conflict, which is a slow very memory
++ # consuming and fragmenting process. To avoid this, we pick a random,
++ # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
++ # time. Moving up from 0x10000000 also allows more sbrk(2) space.
++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
++ _LT_TAGVAR(archive_expsym_cmds, $1)='$SED "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
++ ;;
++ irix5* | irix6*)
++ case $cc_basename in
++ CC*)
++ # SGI C++
++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
++
++ # Archives containing C++ object files must be created using
++ # "CC -ar", where "CC" is the IRIX C++ compiler. This is
++ # necessary to make sure instantiated templates are included
++ # in the archive.
++ _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs'
++ ;;
++ *)
++ if test yes = "$GXX"; then
++ if test no = "$with_gnu_ld"; then
++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
++ else
++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib'
++ fi
++ fi
++ _LT_TAGVAR(link_all_deplibs, $1)=yes
++ ;;
++ esac
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
++ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
++ _LT_TAGVAR(inherit_rpath, $1)=yes
++ ;;
++
++ linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
++ case $cc_basename in
++ KCC*)
++ # Kuck and Associates, Inc. (KAI) C++ Compiler
++
++ # KCC will only create a shared library if the output file
++ # ends with ".so" (or ".sl" for HP-UX), so rename the library
++ # to its proper name (with version) after linking.
++ _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
++ _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib'
++ # Commands to make compiler produce verbose output that lists
++ # what "hidden" libraries, object files and flags are used when
++ # linking a shared library.
++ #
++ # There doesn't appear to be a way to prevent this compiler from
++ # explicitly linking system object files so we need to strip them
++ # from the output so that they don't get included in the library
++ # dependencies.
++ output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
++
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
++ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
++
++ # Archives containing C++ object files must be created using
++ # "CC -Bstatic", where "CC" is the KAI C++ compiler.
++ _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs'
++ ;;
++ icpc* | ecpc* )
++ # Intel C++
++ with_gnu_ld=yes
++ # version 8.0 and above of icpc choke on multiply defined symbols
++ # if we add $predep_objects and $postdep_objects, however 7.1 and
++ # earlier do not add the objects themselves.
++ case `$CC -V 2>&1` in
++ *"Version 7."*)
++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
++ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
++ ;;
++ *) # Version 8.0 or newer
++ tmp_idyn=
++ case $host_cpu in
++ ia64*) tmp_idyn=' -i_dynamic';;
++ esac
++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
++ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
++ ;;
++ esac
++ _LT_TAGVAR(archive_cmds_need_lc, $1)=no
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
++ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
++ _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive'
++ ;;
++ pgCC* | pgcpp*)
++ # Portland Group C++ compiler
++ case `$CC -V` in
++ *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*)
++ _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~
++ rm -rf $tpldir~
++ $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~
++ compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"'
++ _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~
++ rm -rf $tpldir~
++ $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~
++ $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~
++ $RANLIB $oldlib'
++ _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~
++ rm -rf $tpldir~
++ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
++ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
++ _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~
++ rm -rf $tpldir~
++ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
++ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
++ ;;
++ *) # Version 6 and above use weak symbols
++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
++ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
++ ;;
++ esac
++
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl--rpath $wl$libdir'
++ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
++ _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
++ ;;
++ cxx*)
++ # Compaq C++
++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
++ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib $wl-retain-symbols-file $wl$export_symbols'
++
++ runpath_var=LD_RUN_PATH
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
++ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
++
++ # Commands to make compiler produce verbose output that lists
++ # what "hidden" libraries, object files and flags are used when
++ # linking a shared library.
++ #
++ # There doesn't appear to be a way to prevent this compiler from
++ # explicitly linking system object files so we need to strip them
++ # from the output so that they don't get included in the library
++ # dependencies.
++ output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed'
++ ;;
++ xl* | mpixl* | bgxl*)
++ # IBM XL 8.0 on PPC, with GNU ld
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
++ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
++ _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
++ if test yes = "$supports_anon_versioning"; then
++ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
++ cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
++ echo "local: *; };" >> $output_objdir/$libname.ver~
++ $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib'
++ fi
++ ;;
++ *)
++ case `$CC -V 2>&1 | $SED 5q` in
++ *Sun\ C*)
++ # Sun C++ 5.9
++ _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs'
++ _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
++ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols'
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
++ _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
++ _LT_TAGVAR(compiler_needs_object, $1)=yes
++
++ # Not sure whether something based on
++ # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1
++ # would be better.
++ output_verbose_link_cmd='func_echo_all'
++
++ # Archives containing C++ object files must be created using
++ # "CC -xar", where "CC" is the Sun C++ compiler. This is
++ # necessary to make sure instantiated templates are included
++ # in the archive.
++ _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
++ ;;
++ esac
++ ;;
++ esac
++ ;;
++
++ lynxos*)
++ # FIXME: insert proper C++ library support
++ _LT_TAGVAR(ld_shlibs, $1)=no
++ ;;
++
++ m88k*)
++ # FIXME: insert proper C++ library support
++ _LT_TAGVAR(ld_shlibs, $1)=no
++ ;;
++
++ mvs*)
++ case $cc_basename in
++ cxx*)
++ # FIXME: insert proper C++ library support
++ _LT_TAGVAR(ld_shlibs, $1)=no
++ ;;
++ *)
++ # FIXME: insert proper C++ library support
++ _LT_TAGVAR(ld_shlibs, $1)=no
++ ;;
++ esac
++ ;;
++
++ netbsd*)
++ if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
++ _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags'
++ wlarc=
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
++ _LT_TAGVAR(hardcode_direct, $1)=yes
++ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
++ fi
++ # Workaround some broken pre-1.5 toolchains
++ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"'
++ ;;
++
++ *nto* | *qnx*)
++ _LT_TAGVAR(ld_shlibs, $1)=yes
++ ;;
++
++ openbsd* | bitrig*)
++ if test -f /usr/libexec/ld.so; then
++ _LT_TAGVAR(hardcode_direct, $1)=yes
++ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
++ _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
++ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then
++ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib'
++ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
++ _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive'
++ fi
++ output_verbose_link_cmd=func_echo_all
++ else
++ _LT_TAGVAR(ld_shlibs, $1)=no
++ fi
++ ;;
++
++ osf3* | osf4* | osf5*)
++ case $cc_basename in
++ KCC*)
++ # Kuck and Associates, Inc. (KAI) C++ Compiler
++
++ # KCC will only create a shared library if the output file
++ # ends with ".so" (or ".sl" for HP-UX), so rename the library
++ # to its proper name (with version) after linking.
++ _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
++
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
++ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
++
++ # Archives containing C++ object files must be created using
++ # the KAI C++ compiler.
++ case $host in
++ osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;;
++ *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;;
++ esac
++ ;;
++ RCC*)
++ # Rational C++ 2.4.1
++ # FIXME: insert proper C++ library support
++ _LT_TAGVAR(ld_shlibs, $1)=no
++ ;;
++ cxx*)
++ case $host in
++ osf3*)
++ _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*'
++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
++ ;;
++ *)
++ _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
++ _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~
++ echo "-hidden">> $lib.exp~
++ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~
++ $RM $lib.exp'
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
++ ;;
++ esac
++
++ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
++
++ # Commands to make compiler produce verbose output that lists
++ # what "hidden" libraries, object files and flags are used when
++ # linking a shared library.
++ #
++ # There doesn't appear to be a way to prevent this compiler from
++ # explicitly linking system object files so we need to strip them
++ # from the output so that they don't get included in the library
++ # dependencies.
++ output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
++ ;;
++ *)
++ if test yes,no = "$GXX,$with_gnu_ld"; then
++ _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*'
++ case $host in
++ osf3*)
++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
++ ;;
++ *)
++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
++ ;;
++ esac
++
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
++ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
++
++ # Commands to make compiler produce verbose output that lists
++ # what "hidden" libraries, object files and flags are used when
++ # linking a shared library.
++ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
++
++ else
++ # FIXME: insert proper C++ library support
++ _LT_TAGVAR(ld_shlibs, $1)=no
++ fi
++ ;;
++ esac
++ ;;
++
++ psos*)
++ # FIXME: insert proper C++ library support
++ _LT_TAGVAR(ld_shlibs, $1)=no
++ ;;
++
++ sunos4*)
++ case $cc_basename in
++ CC*)
++ # Sun C++ 4.x
++ # FIXME: insert proper C++ library support
++ _LT_TAGVAR(ld_shlibs, $1)=no
++ ;;
++ lcc*)
++ # Lucid
++ # FIXME: insert proper C++ library support
++ _LT_TAGVAR(ld_shlibs, $1)=no
++ ;;
++ *)
++ # FIXME: insert proper C++ library support
++ _LT_TAGVAR(ld_shlibs, $1)=no
++ ;;
++ esac
++ ;;
++
++ solaris*)
++ case $cc_basename in
++ CC* | sunCC*)
++ # Sun C++ 4.2, 5.x and Centerline C++
++ _LT_TAGVAR(archive_cmds_need_lc,$1)=yes
++ _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs'
++ _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
++ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
++ $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
++
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
++ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
++ case $host_os in
++ solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
++ *)
++ # The compiler driver will combine and reorder linker options,
++ # but understands '-z linker_flag'.
++ # Supported since Solaris 2.6 (maybe 2.5.1?)
++ _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract'
++ ;;
++ esac
++ _LT_TAGVAR(link_all_deplibs, $1)=yes
++
++ output_verbose_link_cmd='func_echo_all'
++
++ # Archives containing C++ object files must be created using
++ # "CC -xar", where "CC" is the Sun C++ compiler. This is
++ # necessary to make sure instantiated templates are included
++ # in the archive.
++ _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
++ ;;
++ gcx*)
++ # Green Hills C++ Compiler
++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib'
++
++ # The C++ compiler must be used to create the archive.
++ _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs'
++ ;;
++ *)
++ # GNU C++ compiler with Solaris linker
++ if test yes,no = "$GXX,$with_gnu_ld"; then
++ _LT_TAGVAR(no_undefined_flag, $1)=' $wl-z ${wl}defs'
++ if $CC --version | $GREP -v '^2\.7' > /dev/null; then
++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib'
++ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
++ $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
++
++ # Commands to make compiler produce verbose output that lists
++ # what "hidden" libraries, object files and flags are used when
++ # linking a shared library.
++ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
++ else
++ # g++ 2.7 appears to require '-G' NOT '-shared' on this
++ # platform.
++ _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib'
++ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
++ $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
++
++ # Commands to make compiler produce verbose output that lists
++ # what "hidden" libraries, object files and flags are used when
++ # linking a shared library.
++ output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
++ fi
++
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $wl$libdir'
++ case $host_os in
++ solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
++ *)
++ _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract'
++ ;;
++ esac
++ fi
++ ;;
++ esac
++ ;;
++
++ sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*)
++ _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text'
++ _LT_TAGVAR(archive_cmds_need_lc, $1)=no
++ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
++ runpath_var='LD_RUN_PATH'
++
++ case $cc_basename in
++ CC*)
++ _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++ ;;
++ *)
++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++ ;;
++ esac
++ ;;
++
++ sysv5* | sco3.2v5* | sco5v6*)
++ # Note: We CANNOT use -z defs as we might desire, because we do not
++ # link with -lc, and that would cause any symbols used from libc to
++ # always be unresolved, which means just about no library would
++ # ever link correctly. If we're not using GNU ld we use -z text
++ # though, which does catch some bad symbols but isn't as heavy-handed
++ # as -z defs.
++ _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text'
++ _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs'
++ _LT_TAGVAR(archive_cmds_need_lc, $1)=no
++ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
++ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir'
++ _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
++ _LT_TAGVAR(link_all_deplibs, $1)=yes
++ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport'
++ runpath_var='LD_RUN_PATH'
++
++ case $cc_basename in
++ CC*)
++ _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++ _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~
++ '"$_LT_TAGVAR(old_archive_cmds, $1)"
++ _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~
++ '"$_LT_TAGVAR(reload_cmds, $1)"
++ ;;
++ *)
++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++ ;;
++ esac
++ ;;
++
++ tandem*)
++ case $cc_basename in
++ NCC*)
++ # NonStop-UX NCC 3.20
++ # FIXME: insert proper C++ library support
++ _LT_TAGVAR(ld_shlibs, $1)=no
++ ;;
++ *)
++ # FIXME: insert proper C++ library support
++ _LT_TAGVAR(ld_shlibs, $1)=no
++ ;;
++ esac
++ ;;
++
++ vxworks*)
++ # FIXME: insert proper C++ library support
++ _LT_TAGVAR(ld_shlibs, $1)=no
++ ;;
++
++ *)
++ # FIXME: insert proper C++ library support
++ _LT_TAGVAR(ld_shlibs, $1)=no
++ ;;
++ esac
++
++ AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)])
++ test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no
++
++ _LT_TAGVAR(GCC, $1)=$GXX
++ _LT_TAGVAR(LD, $1)=$LD
++
++ ## CAVEAT EMPTOR:
++ ## There is no encapsulation within the following macros, do not change
++ ## the running order or otherwise move them around unless you know exactly
++ ## what you are doing...
++ _LT_SYS_HIDDEN_LIBDEPS($1)
++ _LT_COMPILER_PIC($1)
++ _LT_COMPILER_C_O($1)
++ _LT_COMPILER_FILE_LOCKS($1)
++ _LT_LINKER_SHLIBS($1)
++ _LT_SYS_DYNAMIC_LINKER($1)
++ _LT_LINKER_HARDCODE_LIBPATH($1)
++
++ _LT_CONFIG($1)
++ fi # test -n "$compiler"
++
++ CC=$lt_save_CC
++ CFLAGS=$lt_save_CFLAGS
++ LDCXX=$LD
++ LD=$lt_save_LD
++ GCC=$lt_save_GCC
++ with_gnu_ld=$lt_save_with_gnu_ld
++ lt_cv_path_LDCXX=$lt_cv_path_LD
++ lt_cv_path_LD=$lt_save_path_LD
++ lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld
++ lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld
++fi # test yes != "$_lt_caught_CXX_error"
++
++AC_LANG_POP
++])# _LT_LANG_CXX_CONFIG
++
++
++# _LT_FUNC_STRIPNAME_CNF
++# ----------------------
++# func_stripname_cnf prefix suffix name
++# strip PREFIX and SUFFIX off of NAME.
++# PREFIX and SUFFIX must not contain globbing or regex special
++# characters, hashes, percent signs, but SUFFIX may contain a leading
++# dot (in which case that matches only a dot).
++#
++# This function is identical to the (non-XSI) version of func_stripname,
++# except this one can be used by m4 code that may be executed by configure,
++# rather than the libtool script.
++m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl
++AC_REQUIRE([_LT_DECL_SED])
++AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])
++func_stripname_cnf ()
++{
++ case @S|@2 in
++ .*) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%\\\\@S|@2\$%%"`;;
++ *) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%@S|@2\$%%"`;;
++ esac
++} # func_stripname_cnf
++])# _LT_FUNC_STRIPNAME_CNF
++
++
++# _LT_SYS_HIDDEN_LIBDEPS([TAGNAME])
++# ---------------------------------
++# Figure out "hidden" library dependencies from verbose
++# compiler output when linking a shared library.
++# Parse the compiler output and extract the necessary
++# objects, libraries and library flags.
++m4_defun([_LT_SYS_HIDDEN_LIBDEPS],
++[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
++AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl
++# Dependencies to place before and after the object being linked:
++_LT_TAGVAR(predep_objects, $1)=
++_LT_TAGVAR(postdep_objects, $1)=
++_LT_TAGVAR(predeps, $1)=
++_LT_TAGVAR(postdeps, $1)=
++_LT_TAGVAR(compiler_lib_search_path, $1)=
++
++dnl we can't use the lt_simple_compile_test_code here,
++dnl because it contains code intended for an executable,
++dnl not a library. It's possible we should let each
++dnl tag define a new lt_????_link_test_code variable,
++dnl but it's only used here...
++m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF
++int a;
++void foo (void) { a = 0; }
++_LT_EOF
++], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF
++class Foo
++{
++public:
++ Foo (void) { a = 0; }
++private:
++ int a;
++};
++_LT_EOF
++], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF
++ subroutine foo
++ implicit none
++ integer*4 a
++ a=0
++ return
++ end
++_LT_EOF
++], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF
++ subroutine foo
++ implicit none
++ integer a
++ a=0
++ return
++ end
++_LT_EOF
++], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF
++public class foo {
++ private int a;
++ public void bar (void) {
++ a = 0;
++ }
++};
++_LT_EOF
++], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF
++package foo
++func foo() {
++}
++_LT_EOF
++])
++
++_lt_libdeps_save_CFLAGS=$CFLAGS
++case "$CC $CFLAGS " in #(
++*\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;;
++*\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;;
++*\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;;
++esac
++
++dnl Parse the compiler output and extract the necessary
++dnl objects, libraries and library flags.
++if AC_TRY_EVAL(ac_compile); then
++ # Parse the compiler output and extract the necessary
++ # objects, libraries and library flags.
++
++ # Sentinel used to keep track of whether or not we are before
++ # the conftest object file.
++ pre_test_object_deps_done=no
++
++ for p in `eval "$output_verbose_link_cmd"`; do
++ case $prev$p in
++
++ -L* | -R* | -l*)
++ # Some compilers place space between "-{L,R}" and the path.
++ # Remove the space.
++ if test x-L = "$p" ||
++ test x-R = "$p"; then
++ prev=$p
++ continue
++ fi
++
++ # Expand the sysroot to ease extracting the directories later.
++ if test -z "$prev"; then
++ case $p in
++ -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;;
++ -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;;
++ -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;;
++ esac
++ fi
++ case $p in
++ =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;;
++ esac
++ if test no = "$pre_test_object_deps_done"; then
++ case $prev in
++ -L | -R)
++ # Internal compiler library paths should come after those
++ # provided the user. The postdeps already come after the
++ # user supplied libs so there is no need to process them.
++ if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then
++ _LT_TAGVAR(compiler_lib_search_path, $1)=$prev$p
++ else
++ _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} $prev$p"
++ fi
++ ;;
++ # The "-l" case would never come before the object being
++ # linked, so don't bother handling this case.
++ esac
++ else
++ if test -z "$_LT_TAGVAR(postdeps, $1)"; then
++ _LT_TAGVAR(postdeps, $1)=$prev$p
++ else
++ _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} $prev$p"
++ fi
++ fi
++ prev=
++ ;;
++
++ *.lto.$objext) ;; # Ignore GCC LTO objects
++ *.$objext)
++ # This assumes that the test object file only shows up
++ # once in the compiler output.
++ if test "$p" = "conftest.$objext"; then
++ pre_test_object_deps_done=yes
++ continue
++ fi
++
++ if test no = "$pre_test_object_deps_done"; then
++ if test -z "$_LT_TAGVAR(predep_objects, $1)"; then
++ _LT_TAGVAR(predep_objects, $1)=$p
++ else
++ _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p"
++ fi
++ else
++ if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then
++ _LT_TAGVAR(postdep_objects, $1)=$p
++ else
++ _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p"
++ fi
++ fi
++ ;;
++
++ *) ;; # Ignore the rest.
++
++ esac
++ done
++
++ # Clean up.
++ rm -f a.out a.exe
++else
++ echo "libtool.m4: error: problem compiling $1 test program"
++fi
++
++$RM -f confest.$objext
++CFLAGS=$_lt_libdeps_save_CFLAGS
++
++# PORTME: override above test on systems where it is broken
++m4_if([$1], [CXX],
++[case $host_os in
++interix[[3-9]]*)
++ # Interix 3.5 installs completely hosed .la files for C++, so rather than
++ # hack all around it, let's just trust "g++" to DTRT.
++ _LT_TAGVAR(predep_objects,$1)=
++ _LT_TAGVAR(postdep_objects,$1)=
++ _LT_TAGVAR(postdeps,$1)=
++ ;;
++esac
++])
++
++case " $_LT_TAGVAR(postdeps, $1) " in
++*" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;;
++esac
++ _LT_TAGVAR(compiler_lib_search_dirs, $1)=
++if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then
++ _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | $SED -e 's! -L! !g' -e 's!^ !!'`
++fi
++_LT_TAGDECL([], [compiler_lib_search_dirs], [1],
++ [The directories searched by this compiler when creating a shared library])
++_LT_TAGDECL([], [predep_objects], [1],
++ [Dependencies to place before and after the objects being linked to
++ create a shared library])
++_LT_TAGDECL([], [postdep_objects], [1])
++_LT_TAGDECL([], [predeps], [1])
++_LT_TAGDECL([], [postdeps], [1])
++_LT_TAGDECL([], [compiler_lib_search_path], [1],
++ [The library search path used internally by the compiler when linking
++ a shared library])
++])# _LT_SYS_HIDDEN_LIBDEPS
++
++
++# _LT_LANG_F77_CONFIG([TAG])
++# --------------------------
++# Ensure that the configuration variables for a Fortran 77 compiler are
++# suitably defined. These variables are subsequently used by _LT_CONFIG
++# to write the compiler configuration to 'libtool'.
++m4_defun([_LT_LANG_F77_CONFIG],
++[AC_LANG_PUSH(Fortran 77)
++if test -z "$F77" || test no = "$F77"; then
++ _lt_disable_F77=yes
++fi
++
++_LT_TAGVAR(archive_cmds_need_lc, $1)=no
++_LT_TAGVAR(allow_undefined_flag, $1)=
++_LT_TAGVAR(always_export_symbols, $1)=no
++_LT_TAGVAR(archive_expsym_cmds, $1)=
++_LT_TAGVAR(export_dynamic_flag_spec, $1)=
++_LT_TAGVAR(hardcode_direct, $1)=no
++_LT_TAGVAR(hardcode_direct_absolute, $1)=no
++_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
++_LT_TAGVAR(hardcode_libdir_separator, $1)=
++_LT_TAGVAR(hardcode_minus_L, $1)=no
++_LT_TAGVAR(hardcode_automatic, $1)=no
++_LT_TAGVAR(inherit_rpath, $1)=no
++_LT_TAGVAR(module_cmds, $1)=
++_LT_TAGVAR(module_expsym_cmds, $1)=
++_LT_TAGVAR(link_all_deplibs, $1)=unknown
++_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
++_LT_TAGVAR(reload_flag, $1)=$reload_flag
++_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
++_LT_TAGVAR(no_undefined_flag, $1)=
++_LT_TAGVAR(whole_archive_flag_spec, $1)=
++_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
++
++# Source file extension for f77 test sources.
++ac_ext=f
++
++# Object file extension for compiled f77 test sources.
++objext=o
++_LT_TAGVAR(objext, $1)=$objext
++
++# No sense in running all these tests if we already determined that
++# the F77 compiler isn't working. Some variables (like enable_shared)
++# are currently assumed to apply to all compilers on this platform,
++# and will be corrupted by setting them based on a non-working compiler.
++if test yes != "$_lt_disable_F77"; then
++ # Code to be used in simple compile tests
++ lt_simple_compile_test_code="\
++ subroutine t
++ return
++ end
++"
++
++ # Code to be used in simple link tests
++ lt_simple_link_test_code="\
++ program t
++ end
++"
++
++ # ltmain only uses $CC for tagged configurations so make sure $CC is set.
++ _LT_TAG_COMPILER
++
++ # save warnings/boilerplate of simple test code
++ _LT_COMPILER_BOILERPLATE
++ _LT_LINKER_BOILERPLATE
++
++ # Allow CC to be a program name with arguments.
++ lt_save_CC=$CC
++ lt_save_GCC=$GCC
++ lt_save_CFLAGS=$CFLAGS
++ CC=${F77-"f77"}
++ CFLAGS=$FFLAGS
++ compiler=$CC
++ _LT_TAGVAR(compiler, $1)=$CC
++ _LT_CC_BASENAME([$compiler])
++ GCC=$G77
++ if test -n "$compiler"; then
++ AC_MSG_CHECKING([if libtool supports shared libraries])
++ AC_MSG_RESULT([$can_build_shared])
++
++ AC_MSG_CHECKING([whether to build shared libraries])
++ test no = "$can_build_shared" && enable_shared=no
++
++ # On AIX, shared libraries and static libraries use the same namespace, and
++ # are all built from PIC.
++ case $host_os in
++ aix3*)
++ test yes = "$enable_shared" && enable_static=no
++ if test -n "$RANLIB"; then
++ archive_cmds="$archive_cmds~\$RANLIB \$lib"
++ postinstall_cmds='$RANLIB $lib'
++ fi
++ ;;
++ aix[[4-9]]*)
++ if test ia64 != "$host_cpu"; then
++ case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in
++ yes,aix,yes) ;; # shared object as lib.so file only
++ yes,svr4,*) ;; # shared object as lib.so archive member only
++ yes,*) enable_static=no ;; # shared object in lib.a archive as well
++ esac
++ fi
++ ;;
++ esac
++ AC_MSG_RESULT([$enable_shared])
++
++ AC_MSG_CHECKING([whether to build static libraries])
++ # Make sure either enable_shared or enable_static is yes.
++ test yes = "$enable_shared" || enable_static=yes
++ AC_MSG_RESULT([$enable_static])
++
++ _LT_TAGVAR(GCC, $1)=$G77
++ _LT_TAGVAR(LD, $1)=$LD
++
++ ## CAVEAT EMPTOR:
++ ## There is no encapsulation within the following macros, do not change
++ ## the running order or otherwise move them around unless you know exactly
++ ## what you are doing...
++ _LT_COMPILER_PIC($1)
++ _LT_COMPILER_C_O($1)
++ _LT_COMPILER_FILE_LOCKS($1)
++ _LT_LINKER_SHLIBS($1)
++ _LT_SYS_DYNAMIC_LINKER($1)
++ _LT_LINKER_HARDCODE_LIBPATH($1)
++
++ _LT_CONFIG($1)
++ fi # test -n "$compiler"
++
++ GCC=$lt_save_GCC
++ CC=$lt_save_CC
++ CFLAGS=$lt_save_CFLAGS
++fi # test yes != "$_lt_disable_F77"
++
++AC_LANG_POP
++])# _LT_LANG_F77_CONFIG
++
++
++# _LT_LANG_FC_CONFIG([TAG])
++# -------------------------
++# Ensure that the configuration variables for a Fortran compiler are
++# suitably defined. These variables are subsequently used by _LT_CONFIG
++# to write the compiler configuration to 'libtool'.
++m4_defun([_LT_LANG_FC_CONFIG],
++[AC_LANG_PUSH(Fortran)
++
++if test -z "$FC" || test no = "$FC"; then
++ _lt_disable_FC=yes
++fi
++
++_LT_TAGVAR(archive_cmds_need_lc, $1)=no
++_LT_TAGVAR(allow_undefined_flag, $1)=
++_LT_TAGVAR(always_export_symbols, $1)=no
++_LT_TAGVAR(archive_expsym_cmds, $1)=
++_LT_TAGVAR(export_dynamic_flag_spec, $1)=
++_LT_TAGVAR(hardcode_direct, $1)=no
++_LT_TAGVAR(hardcode_direct_absolute, $1)=no
++_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
++_LT_TAGVAR(hardcode_libdir_separator, $1)=
++_LT_TAGVAR(hardcode_minus_L, $1)=no
++_LT_TAGVAR(hardcode_automatic, $1)=no
++_LT_TAGVAR(inherit_rpath, $1)=no
++_LT_TAGVAR(module_cmds, $1)=
++_LT_TAGVAR(module_expsym_cmds, $1)=
++_LT_TAGVAR(link_all_deplibs, $1)=unknown
++_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
++_LT_TAGVAR(reload_flag, $1)=$reload_flag
++_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
++_LT_TAGVAR(no_undefined_flag, $1)=
++_LT_TAGVAR(whole_archive_flag_spec, $1)=
++_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
++
++# Source file extension for fc test sources.
++ac_ext=${ac_fc_srcext-f}
++
++# Object file extension for compiled fc test sources.
++objext=o
++_LT_TAGVAR(objext, $1)=$objext
++
++# No sense in running all these tests if we already determined that
++# the FC compiler isn't working. Some variables (like enable_shared)
++# are currently assumed to apply to all compilers on this platform,
++# and will be corrupted by setting them based on a non-working compiler.
++if test yes != "$_lt_disable_FC"; then
++ # Code to be used in simple compile tests
++ lt_simple_compile_test_code="\
++ subroutine t
++ return
++ end
++"
++
++ # Code to be used in simple link tests
++ lt_simple_link_test_code="\
++ program t
++ end
++"
++
++ # ltmain only uses $CC for tagged configurations so make sure $CC is set.
++ _LT_TAG_COMPILER
++
++ # save warnings/boilerplate of simple test code
++ _LT_COMPILER_BOILERPLATE
++ _LT_LINKER_BOILERPLATE
++
++ # Allow CC to be a program name with arguments.
++ lt_save_CC=$CC
++ lt_save_GCC=$GCC
++ lt_save_CFLAGS=$CFLAGS
++ CC=${FC-"f95"}
++ CFLAGS=$FCFLAGS
++ compiler=$CC
++ GCC=$ac_cv_fc_compiler_gnu
++
++ _LT_TAGVAR(compiler, $1)=$CC
++ _LT_CC_BASENAME([$compiler])
++
++ if test -n "$compiler"; then
++ AC_MSG_CHECKING([if libtool supports shared libraries])
++ AC_MSG_RESULT([$can_build_shared])
++
++ AC_MSG_CHECKING([whether to build shared libraries])
++ test no = "$can_build_shared" && enable_shared=no
++
++ # On AIX, shared libraries and static libraries use the same namespace, and
++ # are all built from PIC.
++ case $host_os in
++ aix3*)
++ test yes = "$enable_shared" && enable_static=no
++ if test -n "$RANLIB"; then
++ archive_cmds="$archive_cmds~\$RANLIB \$lib"
++ postinstall_cmds='$RANLIB $lib'
++ fi
++ ;;
++ aix[[4-9]]*)
++ if test ia64 != "$host_cpu"; then
++ case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in
++ yes,aix,yes) ;; # shared object as lib.so file only
++ yes,svr4,*) ;; # shared object as lib.so archive member only
++ yes,*) enable_static=no ;; # shared object in lib.a archive as well
++ esac
++ fi
++ ;;
++ esac
++ AC_MSG_RESULT([$enable_shared])
++
++ AC_MSG_CHECKING([whether to build static libraries])
++ # Make sure either enable_shared or enable_static is yes.
++ test yes = "$enable_shared" || enable_static=yes
++ AC_MSG_RESULT([$enable_static])
++
++ _LT_TAGVAR(GCC, $1)=$ac_cv_fc_compiler_gnu
++ _LT_TAGVAR(LD, $1)=$LD
++
++ ## CAVEAT EMPTOR:
++ ## There is no encapsulation within the following macros, do not change
++ ## the running order or otherwise move them around unless you know exactly
++ ## what you are doing...
++ _LT_SYS_HIDDEN_LIBDEPS($1)
++ _LT_COMPILER_PIC($1)
++ _LT_COMPILER_C_O($1)
++ _LT_COMPILER_FILE_LOCKS($1)
++ _LT_LINKER_SHLIBS($1)
++ _LT_SYS_DYNAMIC_LINKER($1)
++ _LT_LINKER_HARDCODE_LIBPATH($1)
++
++ _LT_CONFIG($1)
++ fi # test -n "$compiler"
++
++ GCC=$lt_save_GCC
++ CC=$lt_save_CC
++ CFLAGS=$lt_save_CFLAGS
++fi # test yes != "$_lt_disable_FC"
++
++AC_LANG_POP
++])# _LT_LANG_FC_CONFIG
++
++
++# _LT_LANG_GCJ_CONFIG([TAG])
++# --------------------------
++# Ensure that the configuration variables for the GNU Java Compiler compiler
++# are suitably defined. These variables are subsequently used by _LT_CONFIG
++# to write the compiler configuration to 'libtool'.
++m4_defun([_LT_LANG_GCJ_CONFIG],
++[AC_REQUIRE([LT_PROG_GCJ])dnl
++AC_LANG_SAVE
++
++# Source file extension for Java test sources.
++ac_ext=java
++
++# Object file extension for compiled Java test sources.
++objext=o
++_LT_TAGVAR(objext, $1)=$objext
++
++# Code to be used in simple compile tests
++lt_simple_compile_test_code="class foo {}"
++
++# Code to be used in simple link tests
++lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }'
++
++# ltmain only uses $CC for tagged configurations so make sure $CC is set.
++_LT_TAG_COMPILER
++
++# save warnings/boilerplate of simple test code
++_LT_COMPILER_BOILERPLATE
++_LT_LINKER_BOILERPLATE
++
++# Allow CC to be a program name with arguments.
++lt_save_CC=$CC
++lt_save_CFLAGS=$CFLAGS
++lt_save_GCC=$GCC
++GCC=yes
++CC=${GCJ-"gcj"}
++CFLAGS=$GCJFLAGS
++compiler=$CC
++_LT_TAGVAR(compiler, $1)=$CC
++_LT_TAGVAR(LD, $1)=$LD
++_LT_CC_BASENAME([$compiler])
++
++# GCJ did not exist at the time GCC didn't implicitly link libc in.
++_LT_TAGVAR(archive_cmds_need_lc, $1)=no
++
++_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
++_LT_TAGVAR(reload_flag, $1)=$reload_flag
++_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
++
++if test -n "$compiler"; then
++ _LT_COMPILER_NO_RTTI($1)
++ _LT_COMPILER_PIC($1)
++ _LT_COMPILER_C_O($1)
++ _LT_COMPILER_FILE_LOCKS($1)
++ _LT_LINKER_SHLIBS($1)
++ _LT_LINKER_HARDCODE_LIBPATH($1)
++
++ _LT_CONFIG($1)
++fi
++
++AC_LANG_RESTORE
++
++GCC=$lt_save_GCC
++CC=$lt_save_CC
++CFLAGS=$lt_save_CFLAGS
++])# _LT_LANG_GCJ_CONFIG
++
++
++# _LT_LANG_GO_CONFIG([TAG])
++# --------------------------
++# Ensure that the configuration variables for the GNU Go compiler
++# are suitably defined. These variables are subsequently used by _LT_CONFIG
++# to write the compiler configuration to 'libtool'.
++m4_defun([_LT_LANG_GO_CONFIG],
++[AC_REQUIRE([LT_PROG_GO])dnl
++AC_LANG_SAVE
++
++# Source file extension for Go test sources.
++ac_ext=go
++
++# Object file extension for compiled Go test sources.
++objext=o
++_LT_TAGVAR(objext, $1)=$objext
++
++# Code to be used in simple compile tests
++lt_simple_compile_test_code="package main; func main() { }"
++
++# Code to be used in simple link tests
++lt_simple_link_test_code='package main; func main() { }'
++
++# ltmain only uses $CC for tagged configurations so make sure $CC is set.
++_LT_TAG_COMPILER
++
++# save warnings/boilerplate of simple test code
++_LT_COMPILER_BOILERPLATE
++_LT_LINKER_BOILERPLATE
++
++# Allow CC to be a program name with arguments.
++lt_save_CC=$CC
++lt_save_CFLAGS=$CFLAGS
++lt_save_GCC=$GCC
++GCC=yes
++CC=${GOC-"gccgo"}
++CFLAGS=$GOFLAGS
++compiler=$CC
++_LT_TAGVAR(compiler, $1)=$CC
++_LT_TAGVAR(LD, $1)=$LD
++_LT_CC_BASENAME([$compiler])
++
++# Go did not exist at the time GCC didn't implicitly link libc in.
++_LT_TAGVAR(archive_cmds_need_lc, $1)=no
++
++_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
++_LT_TAGVAR(reload_flag, $1)=$reload_flag
++_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
++
++if test -n "$compiler"; then
++ _LT_COMPILER_NO_RTTI($1)
++ _LT_COMPILER_PIC($1)
++ _LT_COMPILER_C_O($1)
++ _LT_COMPILER_FILE_LOCKS($1)
++ _LT_LINKER_SHLIBS($1)
++ _LT_LINKER_HARDCODE_LIBPATH($1)
++
++ _LT_CONFIG($1)
++fi
++
++AC_LANG_RESTORE
++
++GCC=$lt_save_GCC
++CC=$lt_save_CC
++CFLAGS=$lt_save_CFLAGS
++])# _LT_LANG_GO_CONFIG
++
++
++# _LT_LANG_RC_CONFIG([TAG])
++# -------------------------
++# Ensure that the configuration variables for the Windows resource compiler
++# are suitably defined. These variables are subsequently used by _LT_CONFIG
++# to write the compiler configuration to 'libtool'.
++m4_defun([_LT_LANG_RC_CONFIG],
++[AC_REQUIRE([LT_PROG_RC])dnl
++AC_LANG_SAVE
++
++# Source file extension for RC test sources.
++ac_ext=rc
++
++# Object file extension for compiled RC test sources.
++objext=o
++_LT_TAGVAR(objext, $1)=$objext
++
++# Code to be used in simple compile tests
++lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }'
++
++# Code to be used in simple link tests
++lt_simple_link_test_code=$lt_simple_compile_test_code
++
++# ltmain only uses $CC for tagged configurations so make sure $CC is set.
++_LT_TAG_COMPILER
++
++# save warnings/boilerplate of simple test code
++_LT_COMPILER_BOILERPLATE
++_LT_LINKER_BOILERPLATE
++
++# Allow CC to be a program name with arguments.
++lt_save_CC=$CC
++lt_save_CFLAGS=$CFLAGS
++lt_save_GCC=$GCC
++GCC=
++CC=${RC-"windres"}
++CFLAGS=
++compiler=$CC
++_LT_TAGVAR(compiler, $1)=$CC
++_LT_CC_BASENAME([$compiler])
++_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
++
++if test -n "$compiler"; then
++ :
++ _LT_CONFIG($1)
++fi
++
++GCC=$lt_save_GCC
++AC_LANG_RESTORE
++CC=$lt_save_CC
++CFLAGS=$lt_save_CFLAGS
++])# _LT_LANG_RC_CONFIG
++
++
++# LT_PROG_GCJ
++# -----------
++AC_DEFUN([LT_PROG_GCJ],
++[m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ],
++ [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ],
++ [AC_CHECK_TOOL(GCJ, gcj,)
++ test set = "${GCJFLAGS+set}" || GCJFLAGS="-g -O2"
++ AC_SUBST(GCJFLAGS)])])[]dnl
++])
++
++# Old name:
++AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ])
++dnl aclocal-1.4 backwards compatibility:
++dnl AC_DEFUN([LT_AC_PROG_GCJ], [])
++
++
++# LT_PROG_GO
++# ----------
++AC_DEFUN([LT_PROG_GO],
++[AC_CHECK_TOOL(GOC, gccgo,)
++])
++
++
++# LT_PROG_RC
++# ----------
++AC_DEFUN([LT_PROG_RC],
++[AC_CHECK_TOOL(RC, windres,)
++])
++
++# Old name:
++AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC])
++dnl aclocal-1.4 backwards compatibility:
++dnl AC_DEFUN([LT_AC_PROG_RC], [])
++
++
++# _LT_DECL_EGREP
++# --------------
++# If we don't have a new enough Autoconf to choose the best grep
++# available, choose the one first in the user's PATH.
++m4_defun([_LT_DECL_EGREP],
++[AC_REQUIRE([AC_PROG_EGREP])dnl
++AC_REQUIRE([AC_PROG_FGREP])dnl
++test -z "$GREP" && GREP=grep
++_LT_DECL([], [GREP], [1], [A grep program that handles long lines])
++_LT_DECL([], [EGREP], [1], [An ERE matcher])
++_LT_DECL([], [FGREP], [1], [A literal string matcher])
++dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too
++AC_SUBST([GREP])
++])
++
++
++# _LT_DECL_OBJDUMP
++# --------------
++# If we don't have a new enough Autoconf to choose the best objdump
++# available, choose the one first in the user's PATH.
++m4_defun([_LT_DECL_OBJDUMP],
++[AC_CHECK_TOOL(OBJDUMP, objdump, false)
++test -z "$OBJDUMP" && OBJDUMP=objdump
++_LT_DECL([], [OBJDUMP], [1], [An object symbol dumper])
++AC_SUBST([OBJDUMP])
++])
++
++# _LT_DECL_DLLTOOL
++# ----------------
++# Ensure DLLTOOL variable is set.
++m4_defun([_LT_DECL_DLLTOOL],
++[AC_CHECK_TOOL(DLLTOOL, dlltool, false)
++test -z "$DLLTOOL" && DLLTOOL=dlltool
++_LT_DECL([], [DLLTOOL], [1], [DLL creation program])
++AC_SUBST([DLLTOOL])
++])
++
++# _LT_DECL_FILECMD
++# ----------------
++# Check for a file(cmd) program that can be used to detect file type and magic
++m4_defun([_LT_DECL_FILECMD],
++[AC_CHECK_TOOL([FILECMD], [file], [:])
++_LT_DECL([], [FILECMD], [1], [A file(cmd) program that detects file types])
++])# _LD_DECL_FILECMD
++
++# _LT_DECL_SED
++# ------------
++# Check for a fully-functional sed program, that truncates
++# as few characters as possible. Prefer GNU sed if found.
++m4_defun([_LT_DECL_SED],
++[AC_PROG_SED
++test -z "$SED" && SED=sed
++Xsed="$SED -e 1s/^X//"
++_LT_DECL([], [SED], [1], [A sed program that does not truncate output])
++_LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"],
++ [Sed that helps us avoid accidentally triggering echo(1) options like -n])
++])# _LT_DECL_SED
++
++m4_ifndef([AC_PROG_SED], [
++# NOTE: This macro has been submitted for inclusion into #
++# GNU Autoconf as AC_PROG_SED. When it is available in #
++# a released version of Autoconf we should remove this #
++# macro and use it instead. #
++
++m4_defun([AC_PROG_SED],
++[AC_MSG_CHECKING([for a sed that does not truncate output])
++AC_CACHE_VAL(lt_cv_path_SED,
++[# Loop through the user's path and test for sed and gsed.
++# Then use that list of sed's as ones to test for truncation.
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++ IFS=$as_save_IFS
++ test -z "$as_dir" && as_dir=.
++ for lt_ac_prog in sed gsed; do
++ for ac_exec_ext in '' $ac_executable_extensions; do
++ if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then
++ lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext"
++ fi
++ done
++ done
++done
++IFS=$as_save_IFS
++lt_ac_max=0
++lt_ac_count=0
++# Add /usr/xpg4/bin/sed as it is typically found on Solaris
++# along with /bin/sed that truncates output.
++for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do
++ test ! -f "$lt_ac_sed" && continue
++ cat /dev/null > conftest.in
++ lt_ac_count=0
++ echo $ECHO_N "0123456789$ECHO_C" >conftest.in
++ # Check for GNU sed and select it if it is found.
++ if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then
++ lt_cv_path_SED=$lt_ac_sed
++ break
++ fi
++ while true; do
++ cat conftest.in conftest.in >conftest.tmp
++ mv conftest.tmp conftest.in
++ cp conftest.in conftest.nl
++ echo >>conftest.nl
++ $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break
++ cmp -s conftest.out conftest.nl || break
++ # 10000 chars as input seems more than enough
++ test 10 -lt "$lt_ac_count" && break
++ lt_ac_count=`expr $lt_ac_count + 1`
++ if test "$lt_ac_count" -gt "$lt_ac_max"; then
++ lt_ac_max=$lt_ac_count
++ lt_cv_path_SED=$lt_ac_sed
++ fi
++ done
++done
++])
++SED=$lt_cv_path_SED
++AC_SUBST([SED])
++AC_MSG_RESULT([$SED])
++])#AC_PROG_SED
++])#m4_ifndef
++
++# Old name:
++AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED])
++dnl aclocal-1.4 backwards compatibility:
++dnl AC_DEFUN([LT_AC_PROG_SED], [])
++
++
++# _LT_CHECK_SHELL_FEATURES
++# ------------------------
++# Find out whether the shell is Bourne or XSI compatible,
++# or has some other useful features.
++m4_defun([_LT_CHECK_SHELL_FEATURES],
++[if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
++ lt_unset=unset
++else
++ lt_unset=false
++fi
++_LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl
++
++# test EBCDIC or ASCII
++case `echo X|tr X '\101'` in
++ A) # ASCII based system
++ # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr
++ lt_SP2NL='tr \040 \012'
++ lt_NL2SP='tr \015\012 \040\040'
++ ;;
++ *) # EBCDIC based system
++ lt_SP2NL='tr \100 \n'
++ lt_NL2SP='tr \r\n \100\100'
++ ;;
++esac
++_LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl
++_LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl
++])# _LT_CHECK_SHELL_FEATURES
++
++
++# _LT_PATH_CONVERSION_FUNCTIONS
++# -----------------------------
++# Determine what file name conversion functions should be used by
++# func_to_host_file (and, implicitly, by func_to_host_path). These are needed
++# for certain cross-compile configurations and native mingw.
++m4_defun([_LT_PATH_CONVERSION_FUNCTIONS],
++[AC_REQUIRE([AC_CANONICAL_HOST])dnl
++AC_REQUIRE([AC_CANONICAL_BUILD])dnl
++AC_MSG_CHECKING([how to convert $build file names to $host format])
++AC_CACHE_VAL(lt_cv_to_host_file_cmd,
++[case $host in
++ *-*-mingw* )
++ case $build in
++ *-*-mingw* ) # actually msys
++ lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32
++ ;;
++ *-*-cygwin* )
++ lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32
++ ;;
++ * ) # otherwise, assume *nix
++ lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32
++ ;;
++ esac
++ ;;
++ *-*-cygwin* )
++ case $build in
++ *-*-mingw* ) # actually msys
++ lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin
++ ;;
++ *-*-cygwin* )
++ lt_cv_to_host_file_cmd=func_convert_file_noop
++ ;;
++ * ) # otherwise, assume *nix
++ lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin
++ ;;
++ esac
++ ;;
++ * ) # unhandled hosts (and "normal" native builds)
++ lt_cv_to_host_file_cmd=func_convert_file_noop
++ ;;
++esac
++])
++to_host_file_cmd=$lt_cv_to_host_file_cmd
++AC_MSG_RESULT([$lt_cv_to_host_file_cmd])
++_LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd],
++ [0], [convert $build file names to $host format])dnl
++
++AC_MSG_CHECKING([how to convert $build file names to toolchain format])
++AC_CACHE_VAL(lt_cv_to_tool_file_cmd,
++[#assume ordinary cross tools, or native build.
++lt_cv_to_tool_file_cmd=func_convert_file_noop
++case $host in
++ *-*-mingw* )
++ case $build in
++ *-*-mingw* ) # actually msys
++ lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32
++ ;;
++ esac
++ ;;
++esac
++])
++to_tool_file_cmd=$lt_cv_to_tool_file_cmd
++AC_MSG_RESULT([$lt_cv_to_tool_file_cmd])
++_LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd],
++ [0], [convert $build files to toolchain format])dnl
++])# _LT_PATH_CONVERSION_FUNCTIONS
++
++# Helper functions for option handling. -*- Autoconf -*-
++#
++# Copyright (C) 2004-2005, 2007-2009, 2011-2019, 2021-2022 Free
++# Software Foundation, Inc.
++# Written by Gary V. Vaughan, 2004
++#
++# This file is free software; the Free Software Foundation gives
++# unlimited permission to copy and/or distribute it, with or without
++# modifications, as long as this notice is preserved.
++
++# serial 8 ltoptions.m4
++
++# This is to help aclocal find these macros, as it can't see m4_define.
++AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])])
++
++
++# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME)
++# ------------------------------------------
++m4_define([_LT_MANGLE_OPTION],
++[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])])
++
++
++# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME)
++# ---------------------------------------
++# Set option OPTION-NAME for macro MACRO-NAME, and if there is a
++# matching handler defined, dispatch to it. Other OPTION-NAMEs are
++# saved as a flag.
++m4_define([_LT_SET_OPTION],
++[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl
++m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]),
++ _LT_MANGLE_DEFUN([$1], [$2]),
++ [m4_warning([Unknown $1 option '$2'])])[]dnl
++])
++
++
++# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET])
++# ------------------------------------------------------------
++# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
++m4_define([_LT_IF_OPTION],
++[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])])
++
++
++# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET)
++# -------------------------------------------------------
++# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME
++# are set.
++m4_define([_LT_UNLESS_OPTIONS],
++[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
++ [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option),
++ [m4_define([$0_found])])])[]dnl
++m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3
++])[]dnl
++])
++
++
++# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST)
++# ----------------------------------------
++# OPTION-LIST is a space-separated list of Libtool options associated
++# with MACRO-NAME. If any OPTION has a matching handler declared with
++# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about
++# the unknown option and exit.
++m4_defun([_LT_SET_OPTIONS],
++[# Set options
++m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
++ [_LT_SET_OPTION([$1], _LT_Option)])
++
++m4_if([$1],[LT_INIT],[
++ dnl
++ dnl Simply set some default values (i.e off) if boolean options were not
++ dnl specified:
++ _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no
++ ])
++ _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no
++ ])
++ dnl
++ dnl If no reference was made to various pairs of opposing options, then
++ dnl we run the default mode handler for the pair. For example, if neither
++ dnl 'shared' nor 'disable-shared' was passed, we enable building of shared
++ dnl archives by default:
++ _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED])
++ _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC])
++ _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC])
++ _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install],
++ [_LT_ENABLE_FAST_INSTALL])
++ _LT_UNLESS_OPTIONS([LT_INIT], [aix-soname=aix aix-soname=both aix-soname=svr4],
++ [_LT_WITH_AIX_SONAME([aix])])
++ ])
++])# _LT_SET_OPTIONS
++
++
++
++# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME)
++# -----------------------------------------
++m4_define([_LT_MANGLE_DEFUN],
++[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])])
++
++
++# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE)
++# -----------------------------------------------
++m4_define([LT_OPTION_DEFINE],
++[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl
++])# LT_OPTION_DEFINE
++
++
++# dlopen
++# ------
++LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes
++])
++
++AU_DEFUN([AC_LIBTOOL_DLOPEN],
++[_LT_SET_OPTION([LT_INIT], [dlopen])
++AC_DIAGNOSE([obsolete],
++[$0: Remove this warning and the call to _LT_SET_OPTION when you
++put the 'dlopen' option into LT_INIT's first parameter.])
++])
++
++dnl aclocal-1.4 backwards compatibility:
++dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], [])
++
++
++# win32-dll
++# ---------
++# Declare package support for building win32 dll's.
++LT_OPTION_DEFINE([LT_INIT], [win32-dll],
++[enable_win32_dll=yes
++
++case $host in
++*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*)
++ AC_CHECK_TOOL(AS, as, false)
++ AC_CHECK_TOOL(DLLTOOL, dlltool, false)
++ AC_CHECK_TOOL(OBJDUMP, objdump, false)
++ ;;
++esac
++
++test -z "$AS" && AS=as
++_LT_DECL([], [AS], [1], [Assembler program])dnl
++
++test -z "$DLLTOOL" && DLLTOOL=dlltool
++_LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl
++
++test -z "$OBJDUMP" && OBJDUMP=objdump
++_LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl
++])# win32-dll
++
++AU_DEFUN([AC_LIBTOOL_WIN32_DLL],
++[AC_REQUIRE([AC_CANONICAL_HOST])dnl
++_LT_SET_OPTION([LT_INIT], [win32-dll])
++AC_DIAGNOSE([obsolete],
++[$0: Remove this warning and the call to _LT_SET_OPTION when you
++put the 'win32-dll' option into LT_INIT's first parameter.])
++])
++
++dnl aclocal-1.4 backwards compatibility:
++dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], [])
++
++
++# _LT_ENABLE_SHARED([DEFAULT])
++# ----------------------------
++# implement the --enable-shared flag, and supports the 'shared' and
++# 'disable-shared' LT_INIT options.
++# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'.
++m4_define([_LT_ENABLE_SHARED],
++[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl
++AC_ARG_ENABLE([shared],
++ [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@],
++ [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])],
++ [p=${PACKAGE-default}
++ case $enableval in
++ yes) enable_shared=yes ;;
++ no) enable_shared=no ;;
++ *)
++ enable_shared=no
++ # Look at the argument we got. We use all the common list separators.
++ lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
++ for pkg in $enableval; do
++ IFS=$lt_save_ifs
++ if test "X$pkg" = "X$p"; then
++ enable_shared=yes
++ fi
++ done
++ IFS=$lt_save_ifs
++ ;;
++ esac],
++ [enable_shared=]_LT_ENABLE_SHARED_DEFAULT)
++
++ _LT_DECL([build_libtool_libs], [enable_shared], [0],
++ [Whether or not to build shared libraries])
++])# _LT_ENABLE_SHARED
++
++LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])])
++LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])])
++
++# Old names:
++AC_DEFUN([AC_ENABLE_SHARED],
++[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared])
++])
++
++AC_DEFUN([AC_DISABLE_SHARED],
++[_LT_SET_OPTION([LT_INIT], [disable-shared])
++])
++
++AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)])
++AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)])
++
++dnl aclocal-1.4 backwards compatibility:
++dnl AC_DEFUN([AM_ENABLE_SHARED], [])
++dnl AC_DEFUN([AM_DISABLE_SHARED], [])
++
++
++
++# _LT_ENABLE_STATIC([DEFAULT])
++# ----------------------------
++# implement the --enable-static flag, and support the 'static' and
++# 'disable-static' LT_INIT options.
++# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'.
++m4_define([_LT_ENABLE_STATIC],
++[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl
++AC_ARG_ENABLE([static],
++ [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@],
++ [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])],
++ [p=${PACKAGE-default}
++ case $enableval in
++ yes) enable_static=yes ;;
++ no) enable_static=no ;;
++ *)
++ enable_static=no
++ # Look at the argument we got. We use all the common list separators.
++ lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
++ for pkg in $enableval; do
++ IFS=$lt_save_ifs
++ if test "X$pkg" = "X$p"; then
++ enable_static=yes
++ fi
++ done
++ IFS=$lt_save_ifs
++ ;;
++ esac],
++ [enable_static=]_LT_ENABLE_STATIC_DEFAULT)
++
++ _LT_DECL([build_old_libs], [enable_static], [0],
++ [Whether or not to build static libraries])
++])# _LT_ENABLE_STATIC
++
++LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])])
++LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])])
++
++# Old names:
++AC_DEFUN([AC_ENABLE_STATIC],
++[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static])
++])
++
++AC_DEFUN([AC_DISABLE_STATIC],
++[_LT_SET_OPTION([LT_INIT], [disable-static])
++])
++
++AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)])
++AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)])
++
++dnl aclocal-1.4 backwards compatibility:
++dnl AC_DEFUN([AM_ENABLE_STATIC], [])
++dnl AC_DEFUN([AM_DISABLE_STATIC], [])
++
++
++
++# _LT_ENABLE_FAST_INSTALL([DEFAULT])
++# ----------------------------------
++# implement the --enable-fast-install flag, and support the 'fast-install'
++# and 'disable-fast-install' LT_INIT options.
++# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'.
++m4_define([_LT_ENABLE_FAST_INSTALL],
++[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl
++AC_ARG_ENABLE([fast-install],
++ [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@],
++ [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])],
++ [p=${PACKAGE-default}
++ case $enableval in
++ yes) enable_fast_install=yes ;;
++ no) enable_fast_install=no ;;
++ *)
++ enable_fast_install=no
++ # Look at the argument we got. We use all the common list separators.
++ lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
++ for pkg in $enableval; do
++ IFS=$lt_save_ifs
++ if test "X$pkg" = "X$p"; then
++ enable_fast_install=yes
++ fi
++ done
++ IFS=$lt_save_ifs
++ ;;
++ esac],
++ [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT)
++
++_LT_DECL([fast_install], [enable_fast_install], [0],
++ [Whether or not to optimize for fast installation])dnl
++])# _LT_ENABLE_FAST_INSTALL
++
++LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])])
++LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])])
++
++# Old names:
++AU_DEFUN([AC_ENABLE_FAST_INSTALL],
++[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install])
++AC_DIAGNOSE([obsolete],
++[$0: Remove this warning and the call to _LT_SET_OPTION when you put
++the 'fast-install' option into LT_INIT's first parameter.])
++])
++
++AU_DEFUN([AC_DISABLE_FAST_INSTALL],
++[_LT_SET_OPTION([LT_INIT], [disable-fast-install])
++AC_DIAGNOSE([obsolete],
++[$0: Remove this warning and the call to _LT_SET_OPTION when you put
++the 'disable-fast-install' option into LT_INIT's first parameter.])
++])
++
++dnl aclocal-1.4 backwards compatibility:
++dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], [])
++dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], [])
++
++
++# _LT_WITH_AIX_SONAME([DEFAULT])
++# ----------------------------------
++# implement the --with-aix-soname flag, and support the `aix-soname=aix'
++# and `aix-soname=both' and `aix-soname=svr4' LT_INIT options. DEFAULT
++# is either `aix', `both' or `svr4'. If omitted, it defaults to `aix'.
++m4_define([_LT_WITH_AIX_SONAME],
++[m4_define([_LT_WITH_AIX_SONAME_DEFAULT], [m4_if($1, svr4, svr4, m4_if($1, both, both, aix))])dnl
++shared_archive_member_spec=
++case $host,$enable_shared in
++power*-*-aix[[5-9]]*,yes)
++ AC_MSG_CHECKING([which variant of shared library versioning to provide])
++ AC_ARG_WITH([aix-soname],
++ [AS_HELP_STRING([--with-aix-soname=aix|svr4|both],
++ [shared library versioning (aka "SONAME") variant to provide on AIX, @<:@default=]_LT_WITH_AIX_SONAME_DEFAULT[@:>@.])],
++ [case $withval in
++ aix|svr4|both)
++ ;;
++ *)
++ AC_MSG_ERROR([Unknown argument to --with-aix-soname])
++ ;;
++ esac
++ lt_cv_with_aix_soname=$with_aix_soname],
++ [AC_CACHE_VAL([lt_cv_with_aix_soname],
++ [lt_cv_with_aix_soname=]_LT_WITH_AIX_SONAME_DEFAULT)
++ with_aix_soname=$lt_cv_with_aix_soname])
++ AC_MSG_RESULT([$with_aix_soname])
++ if test aix != "$with_aix_soname"; then
++ # For the AIX way of multilib, we name the shared archive member
++ # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o',
++ # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File.
++ # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag,
++ # the AIX toolchain works better with OBJECT_MODE set (default 32).
++ if test 64 = "${OBJECT_MODE-32}"; then
++ shared_archive_member_spec=shr_64
++ else
++ shared_archive_member_spec=shr
++ fi
++ fi
++ ;;
++*)
++ with_aix_soname=aix
++ ;;
++esac
++
++_LT_DECL([], [shared_archive_member_spec], [0],
++ [Shared archive member basename, for filename based shared library versioning on AIX])dnl
++])# _LT_WITH_AIX_SONAME
++
++LT_OPTION_DEFINE([LT_INIT], [aix-soname=aix], [_LT_WITH_AIX_SONAME([aix])])
++LT_OPTION_DEFINE([LT_INIT], [aix-soname=both], [_LT_WITH_AIX_SONAME([both])])
++LT_OPTION_DEFINE([LT_INIT], [aix-soname=svr4], [_LT_WITH_AIX_SONAME([svr4])])
++
++
++# _LT_WITH_PIC([MODE])
++# --------------------
++# implement the --with-pic flag, and support the 'pic-only' and 'no-pic'
++# LT_INIT options.
++# MODE is either 'yes' or 'no'. If omitted, it defaults to 'both'.
++m4_define([_LT_WITH_PIC],
++[AC_ARG_WITH([pic],
++ [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@],
++ [try to use only PIC/non-PIC objects @<:@default=use both@:>@])],
++ [lt_p=${PACKAGE-default}
++ case $withval in
++ yes|no) pic_mode=$withval ;;
++ *)
++ pic_mode=default
++ # Look at the argument we got. We use all the common list separators.
++ lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
++ for lt_pkg in $withval; do
++ IFS=$lt_save_ifs
++ if test "X$lt_pkg" = "X$lt_p"; then
++ pic_mode=yes
++ fi
++ done
++ IFS=$lt_save_ifs
++ ;;
++ esac],
++ [pic_mode=m4_default([$1], [default])])
++
++_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl
++])# _LT_WITH_PIC
++
++LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])])
++LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])])
++
++# Old name:
++AU_DEFUN([AC_LIBTOOL_PICMODE],
++[_LT_SET_OPTION([LT_INIT], [pic-only])
++AC_DIAGNOSE([obsolete],
++[$0: Remove this warning and the call to _LT_SET_OPTION when you
++put the 'pic-only' option into LT_INIT's first parameter.])
++])
++
++dnl aclocal-1.4 backwards compatibility:
++dnl AC_DEFUN([AC_LIBTOOL_PICMODE], [])
++
++
++m4_define([_LTDL_MODE], [])
++LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive],
++ [m4_define([_LTDL_MODE], [nonrecursive])])
++LT_OPTION_DEFINE([LTDL_INIT], [recursive],
++ [m4_define([_LTDL_MODE], [recursive])])
++LT_OPTION_DEFINE([LTDL_INIT], [subproject],
++ [m4_define([_LTDL_MODE], [subproject])])
++
++m4_define([_LTDL_TYPE], [])
++LT_OPTION_DEFINE([LTDL_INIT], [installable],
++ [m4_define([_LTDL_TYPE], [installable])])
++LT_OPTION_DEFINE([LTDL_INIT], [convenience],
++ [m4_define([_LTDL_TYPE], [convenience])])
++
++# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*-
++#
++# Copyright (C) 2004-2005, 2007-2008, 2011-2019, 2021-2022 Free Software
++# Foundation, Inc.
++# Written by Gary V. Vaughan, 2004
++#
++# This file is free software; the Free Software Foundation gives
++# unlimited permission to copy and/or distribute it, with or without
++# modifications, as long as this notice is preserved.
++
++# serial 6 ltsugar.m4
++
++# This is to help aclocal find these macros, as it can't see m4_define.
++AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])])
++
++
++# lt_join(SEP, ARG1, [ARG2...])
++# -----------------------------
++# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their
++# associated separator.
++# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier
++# versions in m4sugar had bugs.
++m4_define([lt_join],
++[m4_if([$#], [1], [],
++ [$#], [2], [[$2]],
++ [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])])
++m4_define([_lt_join],
++[m4_if([$#$2], [2], [],
++ [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])])
++
++
++# lt_car(LIST)
++# lt_cdr(LIST)
++# ------------
++# Manipulate m4 lists.
++# These macros are necessary as long as will still need to support
++# Autoconf-2.59, which quotes differently.
++m4_define([lt_car], [[$1]])
++m4_define([lt_cdr],
++[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])],
++ [$#], 1, [],
++ [m4_dquote(m4_shift($@))])])
++m4_define([lt_unquote], $1)
++
++
++# lt_append(MACRO-NAME, STRING, [SEPARATOR])
++# ------------------------------------------
++# Redefine MACRO-NAME to hold its former content plus 'SEPARATOR''STRING'.
++# Note that neither SEPARATOR nor STRING are expanded; they are appended
++# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked).
++# No SEPARATOR is output if MACRO-NAME was previously undefined (different
++# than defined and empty).
++#
++# This macro is needed until we can rely on Autoconf 2.62, since earlier
++# versions of m4sugar mistakenly expanded SEPARATOR but not STRING.
++m4_define([lt_append],
++[m4_define([$1],
++ m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])])
++
++
++
++# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...])
++# ----------------------------------------------------------
++# Produce a SEP delimited list of all paired combinations of elements of
++# PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list
++# has the form PREFIXmINFIXSUFFIXn.
++# Needed until we can rely on m4_combine added in Autoconf 2.62.
++m4_define([lt_combine],
++[m4_if(m4_eval([$# > 3]), [1],
++ [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl
++[[m4_foreach([_Lt_prefix], [$2],
++ [m4_foreach([_Lt_suffix],
++ ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[,
++ [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])])
++
++
++# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ])
++# -----------------------------------------------------------------------
++# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited
++# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ.
++m4_define([lt_if_append_uniq],
++[m4_ifdef([$1],
++ [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1],
++ [lt_append([$1], [$2], [$3])$4],
++ [$5])],
++ [lt_append([$1], [$2], [$3])$4])])
++
++
++# lt_dict_add(DICT, KEY, VALUE)
++# -----------------------------
++m4_define([lt_dict_add],
++[m4_define([$1($2)], [$3])])
++
++
++# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE)
++# --------------------------------------------
++m4_define([lt_dict_add_subkey],
++[m4_define([$1($2:$3)], [$4])])
++
++
++# lt_dict_fetch(DICT, KEY, [SUBKEY])
++# ----------------------------------
++m4_define([lt_dict_fetch],
++[m4_ifval([$3],
++ m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]),
++ m4_ifdef([$1($2)], [m4_defn([$1($2)])]))])
++
++
++# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE])
++# -----------------------------------------------------------------
++m4_define([lt_if_dict_fetch],
++[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4],
++ [$5],
++ [$6])])
++
++
++# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...])
++# --------------------------------------------------------------
++m4_define([lt_dict_filter],
++[m4_if([$5], [], [],
++ [lt_join(m4_quote(m4_default([$4], [[, ]])),
++ lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]),
++ [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl
++])
++
++# ltversion.m4 -- version numbers -*- Autoconf -*-
++#
++# Copyright (C) 2004, 2011-2019, 2021-2022 Free Software Foundation,
++# Inc.
++# Written by Scott James Remnant, 2004
++#
++# This file is free software; the Free Software Foundation gives
++# unlimited permission to copy and/or distribute it, with or without
++# modifications, as long as this notice is preserved.
++
++# @configure_input@
++
++# serial 4249 ltversion.m4
++# This file is part of GNU Libtool
++
++m4_define([LT_PACKAGE_VERSION], [2.4.7.4-1ec8f-dirty])
++m4_define([LT_PACKAGE_REVISION], [2.4.7.4])
++
++AC_DEFUN([LTVERSION_VERSION],
++[macro_version='2.4.7.4-1ec8f-dirty'
++macro_revision='2.4.7.4'
++_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?])
++_LT_DECL(, macro_revision, 0)
++])
++
++# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*-
++#
++# Copyright (C) 2004-2005, 2007, 2009, 2011-2019, 2021-2022 Free
++# Software Foundation, Inc.
++# Written by Scott James Remnant, 2004.
++#
++# This file is free software; the Free Software Foundation gives
++# unlimited permission to copy and/or distribute it, with or without
++# modifications, as long as this notice is preserved.
++
++# serial 5 lt~obsolete.m4
++
++# These exist entirely to fool aclocal when bootstrapping libtool.
++#
++# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN),
++# which have later been changed to m4_define as they aren't part of the
++# exported API, or moved to Autoconf or Automake where they belong.
++#
++# The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN
++# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us
++# using a macro with the same name in our local m4/libtool.m4 it'll
++# pull the old libtool.m4 in (it doesn't see our shiny new m4_define
++# and doesn't know about Autoconf macros at all.)
++#
++# So we provide this file, which has a silly filename so it's always
++# included after everything else. This provides aclocal with the
++# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything
++# because those macros already exist, or will be overwritten later.
++# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6.
++#
++# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here.
++# Yes, that means every name once taken will need to remain here until
++# we give up compatibility with versions before 1.7, at which point
++# we need to keep only those names which we still refer to.
++
++# This is to help aclocal find these macros, as it can't see m4_define.
++AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])])
++
++m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])])
++m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])])
++m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])])
++m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])])
++m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])])
++m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])])
++m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])])
++m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])])
++m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])])
++m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])])
++m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])])
++m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])])
++m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])])
++m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])])
++m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])])
++m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])])
++m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])])
++m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])])
++m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])])
++m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])])
++m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])])
++m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])])
++m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])])
++m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])])
++m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])])
++m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])])
++m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])])
++m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])])
++m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])])
++m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])])
++m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])])
++m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])])
++m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])])
++m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])])
++m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])])
++m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])])
++m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])])
++m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])])
++m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])])
++m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])])
++m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])])
++m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])])
++m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])])
++m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])])
++m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])])
++m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])])
++m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])])
++m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])])
++m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])])
++m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])])
++m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])])
++m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])])
++m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])])
++m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])])
++m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])])
++m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])])
++m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])])
++m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])])
++m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])])
++m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])])
++m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])])
++
++# nls.m4 serial 6 (gettext-0.20.2)
++dnl Copyright (C) 1995-2003, 2005-2006, 2008-2014, 2016, 2019-2022 Free
++dnl Software Foundation, Inc.
++dnl This file is free software; the Free Software Foundation
++dnl gives unlimited permission to copy and/or distribute it,
++dnl with or without modifications, as long as this notice is preserved.
++dnl
++dnl This file can be used in projects which are not available under
++dnl the GNU General Public License or the GNU Lesser General Public
++dnl License but which still want to provide support for the GNU gettext
++dnl functionality.
++dnl Please note that the actual code of the GNU gettext library is covered
++dnl by the GNU Lesser General Public License, and the rest of the GNU
++dnl gettext package is covered by the GNU General Public License.
++dnl They are *not* in the public domain.
++
++dnl Authors:
++dnl Ulrich Drepper <drepper@cygnus.com>, 1995-2000.
++dnl Bruno Haible <haible@clisp.cons.org>, 2000-2003.
++
++AC_PREREQ([2.50])
++
++AC_DEFUN([AM_NLS],
++[
++ AC_MSG_CHECKING([whether NLS is requested])
++ dnl Default is enabled NLS
++ AC_ARG_ENABLE([nls],
++ [ --disable-nls do not use Native Language Support],
++ USE_NLS=$enableval, USE_NLS=yes)
++ AC_MSG_RESULT([$USE_NLS])
++ AC_SUBST([USE_NLS])
++])
++
++# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
++# serial 11 (pkg-config-0.29.1)
++
++dnl Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
++dnl Copyright © 2012-2015 Dan Nicholson <dbn.lists@gmail.com>
++dnl
++dnl This program is free software; you can redistribute it and/or modify
++dnl it under the terms of the GNU General Public License as published by
++dnl the Free Software Foundation; either version 2 of the License, or
++dnl (at your option) any later version.
++dnl
++dnl This program is distributed in the hope that it will be useful, but
++dnl WITHOUT ANY WARRANTY; without even the implied warranty of
++dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++dnl General Public License for more details.
++dnl
++dnl You should have received a copy of the GNU General Public License
++dnl along with this program; if not, write to the Free Software
++dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
++dnl 02111-1307, USA.
++dnl
++dnl As a special exception to the GNU General Public License, if you
++dnl distribute this file as part of a program that contains a
++dnl configuration script generated by Autoconf, you may include it under
++dnl the same distribution terms that you use for the rest of that
++dnl program.
++
++dnl PKG_PREREQ(MIN-VERSION)
++dnl -----------------------
++dnl Since: 0.29
++dnl
++dnl Verify that the version of the pkg-config macros are at least
++dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's
++dnl installed version of pkg-config, this checks the developer's version
++dnl of pkg.m4 when generating configure.
++dnl
++dnl To ensure that this macro is defined, also add:
++dnl m4_ifndef([PKG_PREREQ],
++dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])])
++dnl
++dnl See the "Since" comment for each macro you use to see what version
++dnl of the macros you require.
++m4_defun([PKG_PREREQ],
++[m4_define([PKG_MACROS_VERSION], [0.29.1])
++m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1,
++ [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])])
++])dnl PKG_PREREQ
++
++dnl PKG_PROG_PKG_CONFIG([MIN-VERSION])
++dnl ----------------------------------
++dnl Since: 0.16
++dnl
++dnl Search for the pkg-config tool and set the PKG_CONFIG variable to
++dnl first found in the path. Checks that the version of pkg-config found
++dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is
++dnl used since that's the first version where most current features of
++dnl pkg-config existed.
++AC_DEFUN([PKG_PROG_PKG_CONFIG],
++[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
++m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$])
++m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$])
++AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])
++AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path])
++AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path])
++
++if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
++ AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
++fi
++if test -n "$PKG_CONFIG"; then
++ _pkg_min_version=m4_default([$1], [0.9.0])
++ AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version])
++ if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
++ AC_MSG_RESULT([yes])
++ else
++ AC_MSG_RESULT([no])
++ PKG_CONFIG=""
++ fi
++fi[]dnl
++])dnl PKG_PROG_PKG_CONFIG
++
++dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
++dnl -------------------------------------------------------------------
++dnl Since: 0.18
++dnl
++dnl Check to see whether a particular set of modules exists. Similar to
++dnl PKG_CHECK_MODULES(), but does not set variables or print errors.
++dnl
++dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG])
++dnl only at the first occurence in configure.ac, so if the first place
++dnl it's called might be skipped (such as if it is within an "if", you
++dnl have to call PKG_CHECK_EXISTS manually
++AC_DEFUN([PKG_CHECK_EXISTS],
++[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
++if test -n "$PKG_CONFIG" && \
++ AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then
++ m4_default([$2], [:])
++m4_ifvaln([$3], [else
++ $3])dnl
++fi])
++
++dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
++dnl ---------------------------------------------
++dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting
++dnl pkg_failed based on the result.
++m4_define([_PKG_CONFIG],
++[if test -n "$$1"; then
++ pkg_cv_[]$1="$$1"
++ elif test -n "$PKG_CONFIG"; then
++ PKG_CHECK_EXISTS([$3],
++ [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`
++ test "x$?" != "x0" && pkg_failed=yes ],
++ [pkg_failed=yes])
++ else
++ pkg_failed=untried
++fi[]dnl
++])dnl _PKG_CONFIG
++
++dnl _PKG_SHORT_ERRORS_SUPPORTED
++dnl ---------------------------
++dnl Internal check to see if pkg-config supports short errors.
++AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
++[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
++if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
++ _pkg_short_errors_supported=yes
++else
++ _pkg_short_errors_supported=no
++fi[]dnl
++])dnl _PKG_SHORT_ERRORS_SUPPORTED
++
++
++dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
++dnl [ACTION-IF-NOT-FOUND])
++dnl --------------------------------------------------------------
++dnl Since: 0.4.0
++dnl
++dnl Note that if there is a possibility the first call to
++dnl PKG_CHECK_MODULES might not happen, you should be sure to include an
++dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
++AC_DEFUN([PKG_CHECK_MODULES],
++[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
++AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
++AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
++
++pkg_failed=no
++AC_MSG_CHECKING([for $1])
++
++_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
++_PKG_CONFIG([$1][_LIBS], [libs], [$2])
++
++m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS
++and $1[]_LIBS to avoid the need to call pkg-config.
++See the pkg-config man page for more details.])
++
++if test $pkg_failed = yes; then
++ AC_MSG_RESULT([no])
++ _PKG_SHORT_ERRORS_SUPPORTED
++ if test $_pkg_short_errors_supported = yes; then
++ $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1`
++ else
++ $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1`
++ fi
++ # Put the nasty error message in config.log where it belongs
++ echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
++
++ m4_default([$4], [AC_MSG_ERROR(
++[Package requirements ($2) were not met:
++
++$$1_PKG_ERRORS
++
++Consider adjusting the PKG_CONFIG_PATH environment variable if you
++installed software in a non-standard prefix.
++
++_PKG_TEXT])[]dnl
++ ])
++elif test $pkg_failed = untried; then
++ AC_MSG_RESULT([no])
++ m4_default([$4], [AC_MSG_FAILURE(
++[The pkg-config script could not be found or is too old. Make sure it
++is in your PATH or set the PKG_CONFIG environment variable to the full
++path to pkg-config.
++
++_PKG_TEXT
++
++To get pkg-config, see <http://pkg-config.freedesktop.org/>.])[]dnl
++ ])
++else
++ $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
++ $1[]_LIBS=$pkg_cv_[]$1[]_LIBS
++ AC_MSG_RESULT([yes])
++ $3
++fi[]dnl
++])dnl PKG_CHECK_MODULES
++
++
++dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
++dnl [ACTION-IF-NOT-FOUND])
++dnl ---------------------------------------------------------------------
++dnl Since: 0.29
++dnl
++dnl Checks for existence of MODULES and gathers its build flags with
++dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags
++dnl and VARIABLE-PREFIX_LIBS from --libs.
++dnl
++dnl Note that if there is a possibility the first call to
++dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to
++dnl include an explicit call to PKG_PROG_PKG_CONFIG in your
++dnl configure.ac.
++AC_DEFUN([PKG_CHECK_MODULES_STATIC],
++[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
++_save_PKG_CONFIG=$PKG_CONFIG
++PKG_CONFIG="$PKG_CONFIG --static"
++PKG_CHECK_MODULES($@)
++PKG_CONFIG=$_save_PKG_CONFIG[]dnl
++])dnl PKG_CHECK_MODULES_STATIC
++
++
++dnl PKG_INSTALLDIR([DIRECTORY])
++dnl -------------------------
++dnl Since: 0.27
++dnl
++dnl Substitutes the variable pkgconfigdir as the location where a module
++dnl should install pkg-config .pc files. By default the directory is
++dnl $libdir/pkgconfig, but the default can be changed by passing
++dnl DIRECTORY. The user can override through the --with-pkgconfigdir
++dnl parameter.
++AC_DEFUN([PKG_INSTALLDIR],
++[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])])
++m4_pushdef([pkg_description],
++ [pkg-config installation directory @<:@]pkg_default[@:>@])
++AC_ARG_WITH([pkgconfigdir],
++ [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],,
++ [with_pkgconfigdir=]pkg_default)
++AC_SUBST([pkgconfigdir], [$with_pkgconfigdir])
++m4_popdef([pkg_default])
++m4_popdef([pkg_description])
++])dnl PKG_INSTALLDIR
++
++
++dnl PKG_NOARCH_INSTALLDIR([DIRECTORY])
++dnl --------------------------------
++dnl Since: 0.27
++dnl
++dnl Substitutes the variable noarch_pkgconfigdir as the location where a
++dnl module should install arch-independent pkg-config .pc files. By
++dnl default the directory is $datadir/pkgconfig, but the default can be
++dnl changed by passing DIRECTORY. The user can override through the
++dnl --with-noarch-pkgconfigdir parameter.
++AC_DEFUN([PKG_NOARCH_INSTALLDIR],
++[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])])
++m4_pushdef([pkg_description],
++ [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@])
++AC_ARG_WITH([noarch-pkgconfigdir],
++ [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],,
++ [with_noarch_pkgconfigdir=]pkg_default)
++AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir])
++m4_popdef([pkg_default])
++m4_popdef([pkg_description])
++])dnl PKG_NOARCH_INSTALLDIR
++
++
++dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE,
++dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
++dnl -------------------------------------------
++dnl Since: 0.28
++dnl
++dnl Retrieves the value of the pkg-config variable for the given module.
++AC_DEFUN([PKG_CHECK_VAR],
++[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
++AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl
++
++_PKG_CONFIG([$1], [variable="][$3]["], [$2])
++AS_VAR_COPY([$1], [pkg_cv_][$1])
++
++AS_VAR_IF([$1], [""], [$5], [$4])dnl
++])dnl PKG_CHECK_VAR
++
++dnl PKG_WITH_MODULES(VARIABLE-PREFIX, MODULES,
++dnl [ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND],
++dnl [DESCRIPTION], [DEFAULT])
++dnl ------------------------------------------
++dnl
++dnl Prepare a "--with-" configure option using the lowercase
++dnl [VARIABLE-PREFIX] name, merging the behaviour of AC_ARG_WITH and
++dnl PKG_CHECK_MODULES in a single macro.
++AC_DEFUN([PKG_WITH_MODULES],
++[
++m4_pushdef([with_arg], m4_tolower([$1]))
++
++m4_pushdef([description],
++ [m4_default([$5], [build with ]with_arg[ support])])
++
++m4_pushdef([def_arg], [m4_default([$6], [auto])])
++m4_pushdef([def_action_if_found], [AS_TR_SH([with_]with_arg)=yes])
++m4_pushdef([def_action_if_not_found], [AS_TR_SH([with_]with_arg)=no])
++
++m4_case(def_arg,
++ [yes],[m4_pushdef([with_without], [--without-]with_arg)],
++ [m4_pushdef([with_without],[--with-]with_arg)])
++
++AC_ARG_WITH(with_arg,
++ AS_HELP_STRING(with_without, description[ @<:@default=]def_arg[@:>@]),,
++ [AS_TR_SH([with_]with_arg)=def_arg])
++
++AS_CASE([$AS_TR_SH([with_]with_arg)],
++ [yes],[PKG_CHECK_MODULES([$1],[$2],$3,$4)],
++ [auto],[PKG_CHECK_MODULES([$1],[$2],
++ [m4_n([def_action_if_found]) $3],
++ [m4_n([def_action_if_not_found]) $4])])
++
++m4_popdef([with_arg])
++m4_popdef([description])
++m4_popdef([def_arg])
++
++])dnl PKG_WITH_MODULES
++
++dnl PKG_HAVE_WITH_MODULES(VARIABLE-PREFIX, MODULES,
++dnl [DESCRIPTION], [DEFAULT])
++dnl -----------------------------------------------
++dnl
++dnl Convenience macro to trigger AM_CONDITIONAL after PKG_WITH_MODULES
++dnl check._[VARIABLE-PREFIX] is exported as make variable.
++AC_DEFUN([PKG_HAVE_WITH_MODULES],
++[
++PKG_WITH_MODULES([$1],[$2],,,[$3],[$4])
++
++AM_CONDITIONAL([HAVE_][$1],
++ [test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"])
++])dnl PKG_HAVE_WITH_MODULES
++
++dnl PKG_HAVE_DEFINE_WITH_MODULES(VARIABLE-PREFIX, MODULES,
++dnl [DESCRIPTION], [DEFAULT])
++dnl ------------------------------------------------------
++dnl
++dnl Convenience macro to run AM_CONDITIONAL and AC_DEFINE after
++dnl PKG_WITH_MODULES check. HAVE_[VARIABLE-PREFIX] is exported as make
++dnl and preprocessor variable.
++AC_DEFUN([PKG_HAVE_DEFINE_WITH_MODULES],
++[
++PKG_HAVE_WITH_MODULES([$1],[$2],[$3],[$4])
++
++AS_IF([test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"],
++ [AC_DEFINE([HAVE_][$1], 1, [Enable ]m4_tolower([$1])[ support])])
++])dnl PKG_HAVE_DEFINE_WITH_MODULES
++
++# po.m4 serial 32 (gettext-0.21.1)
++dnl Copyright (C) 1995-2014, 2016, 2018-2022 Free Software Foundation, Inc.
++dnl This file is free software; the Free Software Foundation
++dnl gives unlimited permission to copy and/or distribute it,
++dnl with or without modifications, as long as this notice is preserved.
++dnl
++dnl This file can be used in projects which are not available under
++dnl the GNU General Public License or the GNU Lesser General Public
++dnl License but which still want to provide support for the GNU gettext
++dnl functionality.
++dnl Please note that the actual code of the GNU gettext library is covered
++dnl by the GNU Lesser General Public License, and the rest of the GNU
++dnl gettext package is covered by the GNU General Public License.
++dnl They are *not* in the public domain.
++
++dnl Authors:
++dnl Ulrich Drepper <drepper@cygnus.com>, 1995-2000.
++dnl Bruno Haible <haible@clisp.cons.org>, 2000-2003.
++
++AC_PREREQ([2.60])
++
++dnl Checks for all prerequisites of the po subdirectory.
++AC_DEFUN([AM_PO_SUBDIRS],
++[
++ AC_REQUIRE([AC_PROG_MAKE_SET])dnl
++ AC_REQUIRE([AC_PROG_INSTALL])dnl
++ AC_REQUIRE([AC_PROG_MKDIR_P])dnl
++ AC_REQUIRE([AC_PROG_SED])dnl
++ AC_REQUIRE([AM_NLS])dnl
++
++ dnl Release version of the gettext macros. This is used to ensure that
++ dnl the gettext macros and po/Makefile.in.in are in sync.
++ AC_SUBST([GETTEXT_MACRO_VERSION], [0.20])
++
++ dnl Perform the following tests also if --disable-nls has been given,
++ dnl because they are needed for "make dist" to work.
++
++ dnl Search for GNU msgfmt in the PATH.
++ dnl The first test excludes Solaris msgfmt and early GNU msgfmt versions.
++ dnl The second test excludes FreeBSD msgfmt.
++ AM_PATH_PROG_WITH_TEST(MSGFMT, msgfmt,
++ [$ac_dir/$ac_word --statistics /dev/null >&]AS_MESSAGE_LOG_FD[ 2>&1 &&
++ (if $ac_dir/$ac_word --statistics /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi)],
++ :)
++ AC_PATH_PROG([GMSGFMT], [gmsgfmt], [$MSGFMT])
++
++ dnl Test whether it is GNU msgfmt >= 0.15.
++changequote(,)dnl
++ case `$GMSGFMT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in
++ '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) GMSGFMT_015=: ;;
++ *) GMSGFMT_015=$GMSGFMT ;;
++ esac
++changequote([,])dnl
++ AC_SUBST([GMSGFMT_015])
++
++ dnl Search for GNU xgettext 0.12 or newer in the PATH.
++ dnl The first test excludes Solaris xgettext and early GNU xgettext versions.
++ dnl The second test excludes FreeBSD xgettext.
++ AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext,
++ [$ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null >&]AS_MESSAGE_LOG_FD[ 2>&1 &&
++ (if $ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi)],
++ :)
++ dnl Remove leftover from FreeBSD xgettext call.
++ rm -f messages.po
++
++ dnl Test whether it is GNU xgettext >= 0.15.
++changequote(,)dnl
++ case `$XGETTEXT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in
++ '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) XGETTEXT_015=: ;;
++ *) XGETTEXT_015=$XGETTEXT ;;
++ esac
++changequote([,])dnl
++ AC_SUBST([XGETTEXT_015])
++
++ dnl Search for GNU msgmerge 0.11 or newer in the PATH.
++ AM_PATH_PROG_WITH_TEST(MSGMERGE, msgmerge,
++ [$ac_dir/$ac_word --update -q /dev/null /dev/null >&]AS_MESSAGE_LOG_FD[ 2>&1], :)
++
++ dnl Test whether it is GNU msgmerge >= 0.20.
++ if LC_ALL=C $MSGMERGE --help | grep ' --for-msgfmt ' >/dev/null; then
++ MSGMERGE_FOR_MSGFMT_OPTION='--for-msgfmt'
++ else
++ dnl Test whether it is GNU msgmerge >= 0.12.
++ if LC_ALL=C $MSGMERGE --help | grep ' --no-fuzzy-matching ' >/dev/null; then
++ MSGMERGE_FOR_MSGFMT_OPTION='--no-fuzzy-matching --no-location --quiet'
++ else
++ dnl With these old versions, $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) is
++ dnl slow. But this is not a big problem, as such old gettext versions are
++ dnl hardly in use any more.
++ MSGMERGE_FOR_MSGFMT_OPTION='--no-location --quiet'
++ fi
++ fi
++ AC_SUBST([MSGMERGE_FOR_MSGFMT_OPTION])
++
++ dnl Support for AM_XGETTEXT_OPTION.
++ test -n "${XGETTEXT_EXTRA_OPTIONS+set}" || XGETTEXT_EXTRA_OPTIONS=
++ AC_SUBST([XGETTEXT_EXTRA_OPTIONS])
++
++ AC_CONFIG_COMMANDS([po-directories], [[
++ for ac_file in $CONFIG_FILES; do
++ # Support "outfile[:infile[:infile...]]"
++ case "$ac_file" in
++ *:*) ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
++ esac
++ # PO directories have a Makefile.in generated from Makefile.in.in.
++ case "$ac_file" in */Makefile.in)
++ # Adjust a relative srcdir.
++ ac_dir=`echo "$ac_file"|sed 's%/[^/][^/]*$%%'`
++ ac_dir_suffix=/`echo "$ac_dir"|sed 's%^\./%%'`
++ ac_dots=`echo "$ac_dir_suffix"|sed 's%/[^/]*%../%g'`
++ # In autoconf-2.13 it is called $ac_given_srcdir.
++ # In autoconf-2.50 it is called $srcdir.
++ test -n "$ac_given_srcdir" || ac_given_srcdir="$srcdir"
++ case "$ac_given_srcdir" in
++ .) top_srcdir=`echo $ac_dots|sed 's%/$%%'` ;;
++ /*) top_srcdir="$ac_given_srcdir" ;;
++ *) top_srcdir="$ac_dots$ac_given_srcdir" ;;
++ esac
++ # Treat a directory as a PO directory if and only if it has a
++ # POTFILES.in file. This allows packages to have multiple PO
++ # directories under different names or in different locations.
++ if test -f "$ac_given_srcdir/$ac_dir/POTFILES.in"; then
++ rm -f "$ac_dir/POTFILES"
++ test -n "$as_me" && echo "$as_me: creating $ac_dir/POTFILES" || echo "creating $ac_dir/POTFILES"
++ gt_tab=`printf '\t'`
++ cat "$ac_given_srcdir/$ac_dir/POTFILES.in" | sed -e "/^#/d" -e "/^[ ${gt_tab}]*\$/d" -e "s,.*, $top_srcdir/& \\\\," | sed -e "\$s/\(.*\) \\\\/\1/" > "$ac_dir/POTFILES"
++ POMAKEFILEDEPS="POTFILES.in"
++ # ALL_LINGUAS, POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES depend
++ # on $ac_dir but don't depend on user-specified configuration
++ # parameters.
++ if test -f "$ac_given_srcdir/$ac_dir/LINGUAS"; then
++ # The LINGUAS file contains the set of available languages.
++ if test -n "$OBSOLETE_ALL_LINGUAS"; then
++ test -n "$as_me" && echo "$as_me: setting ALL_LINGUAS in configure.in is obsolete" || echo "setting ALL_LINGUAS in configure.in is obsolete"
++ fi
++ ALL_LINGUAS=`sed -e "/^#/d" -e "s/#.*//" "$ac_given_srcdir/$ac_dir/LINGUAS"`
++ POMAKEFILEDEPS="$POMAKEFILEDEPS LINGUAS"
++ else
++ # The set of available languages was given in configure.in.
++ ALL_LINGUAS=$OBSOLETE_ALL_LINGUAS
++ fi
++ # Compute POFILES
++ # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).po)
++ # Compute UPDATEPOFILES
++ # as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update)
++ # Compute DUMMYPOFILES
++ # as $(foreach lang, $(ALL_LINGUAS), $(lang).nop)
++ # Compute GMOFILES
++ # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).gmo)
++ case "$ac_given_srcdir" in
++ .) srcdirpre= ;;
++ *) srcdirpre='$(srcdir)/' ;;
++ esac
++ POFILES=
++ UPDATEPOFILES=
++ DUMMYPOFILES=
++ GMOFILES=
++ for lang in $ALL_LINGUAS; do
++ POFILES="$POFILES $srcdirpre$lang.po"
++ UPDATEPOFILES="$UPDATEPOFILES $lang.po-update"
++ DUMMYPOFILES="$DUMMYPOFILES $lang.nop"
++ GMOFILES="$GMOFILES $srcdirpre$lang.gmo"
++ done
++ # CATALOGS depends on both $ac_dir and the user's LINGUAS
++ # environment variable.
++ INST_LINGUAS=
++ if test -n "$ALL_LINGUAS"; then
++ for presentlang in $ALL_LINGUAS; do
++ useit=no
++ if test "%UNSET%" != "$LINGUAS"; then
++ desiredlanguages="$LINGUAS"
++ else
++ desiredlanguages="$ALL_LINGUAS"
++ fi
++ for desiredlang in $desiredlanguages; do
++ # Use the presentlang catalog if desiredlang is
++ # a. equal to presentlang, or
++ # b. a variant of presentlang (because in this case,
++ # presentlang can be used as a fallback for messages
++ # which are not translated in the desiredlang catalog).
++ case "$desiredlang" in
++ "$presentlang" | "$presentlang"_* | "$presentlang".* | "$presentlang"@*)
++ useit=yes
++ ;;
++ esac
++ done
++ if test $useit = yes; then
++ INST_LINGUAS="$INST_LINGUAS $presentlang"
++ fi
++ done
++ fi
++ CATALOGS=
++ if test -n "$INST_LINGUAS"; then
++ for lang in $INST_LINGUAS; do
++ CATALOGS="$CATALOGS $lang.gmo"
++ done
++ fi
++ test -n "$as_me" && echo "$as_me: creating $ac_dir/Makefile" || echo "creating $ac_dir/Makefile"
++ sed -e "/^POTFILES =/r $ac_dir/POTFILES" -e "/^# Makevars/r $ac_given_srcdir/$ac_dir/Makevars" -e "s|@POFILES@|$POFILES|g" -e "s|@UPDATEPOFILES@|$UPDATEPOFILES|g" -e "s|@DUMMYPOFILES@|$DUMMYPOFILES|g" -e "s|@GMOFILES@|$GMOFILES|g" -e "s|@CATALOGS@|$CATALOGS|g" -e "s|@POMAKEFILEDEPS@|$POMAKEFILEDEPS|g" "$ac_dir/Makefile.in" > "$ac_dir/Makefile"
++ for f in "$ac_given_srcdir/$ac_dir"/Rules-*; do
++ if test -f "$f"; then
++ case "$f" in
++ *.orig | *.bak | *~) ;;
++ *) cat "$f" >> "$ac_dir/Makefile" ;;
++ esac
++ fi
++ done
++ fi
++ ;;
++ esac
++ done]],
++ [# Capture the value of obsolete ALL_LINGUAS because we need it to compute
++ # POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES, CATALOGS.
++ OBSOLETE_ALL_LINGUAS="$ALL_LINGUAS"
++ # Capture the value of LINGUAS because we need it to compute CATALOGS.
++ LINGUAS="${LINGUAS-%UNSET%}"
++ ])
++])
++
++dnl Postprocesses a Makefile in a directory containing PO files.
++AC_DEFUN([AM_POSTPROCESS_PO_MAKEFILE],
++[
++ # When this code is run, in config.status, two variables have already been
++ # set:
++ # - OBSOLETE_ALL_LINGUAS is the value of LINGUAS set in configure.in,
++ # - LINGUAS is the value of the environment variable LINGUAS at configure
++ # time.
++
++changequote(,)dnl
++ # Adjust a relative srcdir.
++ ac_dir=`echo "$ac_file"|sed 's%/[^/][^/]*$%%'`
++ ac_dir_suffix=/`echo "$ac_dir"|sed 's%^\./%%'`
++ ac_dots=`echo "$ac_dir_suffix"|sed 's%/[^/]*%../%g'`
++ # In autoconf-2.13 it is called $ac_given_srcdir.
++ # In autoconf-2.50 it is called $srcdir.
++ test -n "$ac_given_srcdir" || ac_given_srcdir="$srcdir"
++ case "$ac_given_srcdir" in
++ .) top_srcdir=`echo $ac_dots|sed 's%/$%%'` ;;
++ /*) top_srcdir="$ac_given_srcdir" ;;
++ *) top_srcdir="$ac_dots$ac_given_srcdir" ;;
++ esac
++
++ # Find a way to echo strings without interpreting backslash.
++ if test "X`(echo '\t') 2>/dev/null`" = 'X\t'; then
++ gt_echo='echo'
++ else
++ if test "X`(printf '%s\n' '\t') 2>/dev/null`" = 'X\t'; then
++ gt_echo='printf %s\n'
++ else
++ echo_func () {
++ cat <<EOT
++$*
++EOT
++ }
++ gt_echo='echo_func'
++ fi
++ fi
++
++ # A sed script that extracts the value of VARIABLE from a Makefile.
++ tab=`printf '\t'`
++ sed_x_variable='
++# Test if the hold space is empty.
++x
++s/P/P/
++x
++ta
++# Yes it was empty. Look if we have the expected variable definition.
++/^['"${tab}"' ]*VARIABLE['"${tab}"' ]*=/{
++ # Seen the first line of the variable definition.
++ s/^['"${tab}"' ]*VARIABLE['"${tab}"' ]*=//
++ ba
++}
++bd
++:a
++# Here we are processing a line from the variable definition.
++# Remove comment, more precisely replace it with a space.
++s/#.*$/ /
++# See if the line ends in a backslash.
++tb
++:b
++s/\\$//
++# Print the line, without the trailing backslash.
++p
++tc
++# There was no trailing backslash. The end of the variable definition is
++# reached. Clear the hold space.
++s/^.*$//
++x
++bd
++:c
++# A trailing backslash means that the variable definition continues in the
++# next line. Put a nonempty string into the hold space to indicate this.
++s/^.*$/P/
++x
++:d
++'
++changequote([,])dnl
++
++ # Set POTFILES to the value of the Makefile variable POTFILES.
++ sed_x_POTFILES=`$gt_echo "$sed_x_variable" | sed -e '/^ *#/d' -e 's/VARIABLE/POTFILES/g'`
++ POTFILES=`sed -n -e "$sed_x_POTFILES" < "$ac_file"`
++ # Compute POTFILES_DEPS as
++ # $(foreach file, $(POTFILES), $(top_srcdir)/$(file))
++ POTFILES_DEPS=
++ for file in $POTFILES; do
++ POTFILES_DEPS="$POTFILES_DEPS "'$(top_srcdir)/'"$file"
++ done
++ POMAKEFILEDEPS=""
++
++ if test -n "$OBSOLETE_ALL_LINGUAS"; then
++ test -n "$as_me" && echo "$as_me: setting ALL_LINGUAS in configure.in is obsolete" || echo "setting ALL_LINGUAS in configure.in is obsolete"
++ fi
++ if test -f "$ac_given_srcdir/$ac_dir/LINGUAS"; then
++ # The LINGUAS file contains the set of available languages.
++ ALL_LINGUAS=`sed -e "/^#/d" -e "s/#.*//" "$ac_given_srcdir/$ac_dir/LINGUAS"`
++ POMAKEFILEDEPS="$POMAKEFILEDEPS LINGUAS"
++ else
++ # Set ALL_LINGUAS to the value of the Makefile variable LINGUAS.
++ sed_x_LINGUAS=`$gt_echo "$sed_x_variable" | sed -e '/^ *#/d' -e 's/VARIABLE/LINGUAS/g'`
++ ALL_LINGUAS=`sed -n -e "$sed_x_LINGUAS" < "$ac_file"`
++ fi
++ # Compute POFILES
++ # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).po)
++ # Compute UPDATEPOFILES
++ # as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update)
++ # Compute DUMMYPOFILES
++ # as $(foreach lang, $(ALL_LINGUAS), $(lang).nop)
++ # Compute GMOFILES
++ # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).gmo)
++ # Compute PROPERTIESFILES
++ # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(DOMAIN)_$(lang).properties)
++ # Compute CLASSFILES
++ # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(DOMAIN)_$(lang).class)
++ # Compute QMFILES
++ # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).qm)
++ # Compute MSGFILES
++ # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(frob $(lang)).msg)
++ # Compute RESOURCESDLLFILES
++ # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(frob $(lang))/$(DOMAIN).resources.dll)
++ case "$ac_given_srcdir" in
++ .) srcdirpre= ;;
++ *) srcdirpre='$(srcdir)/' ;;
++ esac
++ POFILES=
++ UPDATEPOFILES=
++ DUMMYPOFILES=
++ GMOFILES=
++ PROPERTIESFILES=
++ CLASSFILES=
++ QMFILES=
++ MSGFILES=
++ RESOURCESDLLFILES=
++ for lang in $ALL_LINGUAS; do
++ POFILES="$POFILES $srcdirpre$lang.po"
++ UPDATEPOFILES="$UPDATEPOFILES $lang.po-update"
++ DUMMYPOFILES="$DUMMYPOFILES $lang.nop"
++ GMOFILES="$GMOFILES $srcdirpre$lang.gmo"
++ PROPERTIESFILES="$PROPERTIESFILES \$(srcdir)/\$(DOMAIN)_$lang.properties"
++ CLASSFILES="$CLASSFILES \$(srcdir)/\$(DOMAIN)_$lang.class"
++ QMFILES="$QMFILES $srcdirpre$lang.qm"
++ frobbedlang=`echo $lang | sed -e 's/\..*$//' -e 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'`
++ MSGFILES="$MSGFILES $srcdirpre$frobbedlang.msg"
++ frobbedlang=`echo $lang | sed -e 's/_/-/g' -e 's/^sr-CS/sr-SP/' -e 's/@latin$/-Latn/' -e 's/@cyrillic$/-Cyrl/' -e 's/^sr-SP$/sr-SP-Latn/' -e 's/^uz-UZ$/uz-UZ-Latn/'`
++ RESOURCESDLLFILES="$RESOURCESDLLFILES $srcdirpre$frobbedlang/\$(DOMAIN).resources.dll"
++ done
++ # CATALOGS depends on both $ac_dir and the user's LINGUAS
++ # environment variable.
++ INST_LINGUAS=
++ if test -n "$ALL_LINGUAS"; then
++ for presentlang in $ALL_LINGUAS; do
++ useit=no
++ if test "%UNSET%" != "$LINGUAS"; then
++ desiredlanguages="$LINGUAS"
++ else
++ desiredlanguages="$ALL_LINGUAS"
++ fi
++ for desiredlang in $desiredlanguages; do
++ # Use the presentlang catalog if desiredlang is
++ # a. equal to presentlang, or
++ # b. a variant of presentlang (because in this case,
++ # presentlang can be used as a fallback for messages
++ # which are not translated in the desiredlang catalog).
++ case "$desiredlang" in
++ "$presentlang" | "$presentlang"_* | "$presentlang".* | "$presentlang"@*)
++ useit=yes
++ ;;
++ esac
++ done
++ if test $useit = yes; then
++ INST_LINGUAS="$INST_LINGUAS $presentlang"
++ fi
++ done
++ fi
++ CATALOGS=
++ JAVACATALOGS=
++ QTCATALOGS=
++ TCLCATALOGS=
++ CSHARPCATALOGS=
++ if test -n "$INST_LINGUAS"; then
++ for lang in $INST_LINGUAS; do
++ CATALOGS="$CATALOGS $lang.gmo"
++ JAVACATALOGS="$JAVACATALOGS \$(DOMAIN)_$lang.properties"
++ QTCATALOGS="$QTCATALOGS $lang.qm"
++ frobbedlang=`echo $lang | sed -e 's/\..*$//' -e 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'`
++ TCLCATALOGS="$TCLCATALOGS $frobbedlang.msg"
++ frobbedlang=`echo $lang | sed -e 's/_/-/g' -e 's/^sr-CS/sr-SP/' -e 's/@latin$/-Latn/' -e 's/@cyrillic$/-Cyrl/' -e 's/^sr-SP$/sr-SP-Latn/' -e 's/^uz-UZ$/uz-UZ-Latn/'`
++ CSHARPCATALOGS="$CSHARPCATALOGS $frobbedlang/\$(DOMAIN).resources.dll"
++ done
++ fi
++
++ sed -e "s|@POTFILES_DEPS@|$POTFILES_DEPS|g" -e "s|@POFILES@|$POFILES|g" -e "s|@UPDATEPOFILES@|$UPDATEPOFILES|g" -e "s|@DUMMYPOFILES@|$DUMMYPOFILES|g" -e "s|@GMOFILES@|$GMOFILES|g" -e "s|@PROPERTIESFILES@|$PROPERTIESFILES|g" -e "s|@CLASSFILES@|$CLASSFILES|g" -e "s|@QMFILES@|$QMFILES|g" -e "s|@MSGFILES@|$MSGFILES|g" -e "s|@RESOURCESDLLFILES@|$RESOURCESDLLFILES|g" -e "s|@CATALOGS@|$CATALOGS|g" -e "s|@JAVACATALOGS@|$JAVACATALOGS|g" -e "s|@QTCATALOGS@|$QTCATALOGS|g" -e "s|@TCLCATALOGS@|$TCLCATALOGS|g" -e "s|@CSHARPCATALOGS@|$CSHARPCATALOGS|g" -e 's,^#distdir:,distdir:,' < "$ac_file" > "$ac_file.tmp"
++ tab=`printf '\t'`
++ if grep -l '@TCLCATALOGS@' "$ac_file" > /dev/null; then
++ # Add dependencies that cannot be formulated as a simple suffix rule.
++ for lang in $ALL_LINGUAS; do
++ frobbedlang=`echo $lang | sed -e 's/\..*$//' -e 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'`
++ cat >> "$ac_file.tmp" <<EOF
++$frobbedlang.msg: $lang.po
++${tab}@echo "\$(MSGFMT) -c --tcl -d \$(srcdir) -l $lang $srcdirpre$lang.po"; \
++${tab}\$(MSGFMT) -c --tcl -d "\$(srcdir)" -l $lang $srcdirpre$lang.po || { rm -f "\$(srcdir)/$frobbedlang.msg"; exit 1; }
++EOF
++ done
++ fi
++ if grep -l '@CSHARPCATALOGS@' "$ac_file" > /dev/null; then
++ # Add dependencies that cannot be formulated as a simple suffix rule.
++ for lang in $ALL_LINGUAS; do
++ frobbedlang=`echo $lang | sed -e 's/_/-/g' -e 's/^sr-CS/sr-SP/' -e 's/@latin$/-Latn/' -e 's/@cyrillic$/-Cyrl/' -e 's/^sr-SP$/sr-SP-Latn/' -e 's/^uz-UZ$/uz-UZ-Latn/'`
++ cat >> "$ac_file.tmp" <<EOF
++$frobbedlang/\$(DOMAIN).resources.dll: $lang.po
++${tab}@echo "\$(MSGFMT) -c --csharp -d \$(srcdir) -l $lang $srcdirpre$lang.po -r \$(DOMAIN)"; \
++${tab}\$(MSGFMT) -c --csharp -d "\$(srcdir)" -l $lang $srcdirpre$lang.po -r "\$(DOMAIN)" || { rm -f "\$(srcdir)/$frobbedlang.msg"; exit 1; }
++EOF
++ done
++ fi
++ if test -n "$POMAKEFILEDEPS"; then
++ cat >> "$ac_file.tmp" <<EOF
++Makefile: $POMAKEFILEDEPS
++EOF
++ fi
++ mv "$ac_file.tmp" "$ac_file"
++])
++
++dnl Initializes the accumulator used by AM_XGETTEXT_OPTION.
++AC_DEFUN([AM_XGETTEXT_OPTION_INIT],
++[
++ XGETTEXT_EXTRA_OPTIONS=
++])
++
++dnl Registers an option to be passed to xgettext in the po subdirectory.
++AC_DEFUN([AM_XGETTEXT_OPTION],
++[
++ AC_REQUIRE([AM_XGETTEXT_OPTION_INIT])
++ XGETTEXT_EXTRA_OPTIONS="$XGETTEXT_EXTRA_OPTIONS $1"
++])
++
++# progtest.m4 serial 9 (gettext-0.21.1)
++dnl Copyright (C) 1996-2003, 2005, 2008-2022 Free Software Foundation, Inc.
++dnl This file is free software; the Free Software Foundation
++dnl gives unlimited permission to copy and/or distribute it,
++dnl with or without modifications, as long as this notice is preserved.
++dnl
++dnl This file can be used in projects which are not available under
++dnl the GNU General Public License or the GNU Lesser General Public
++dnl License but which still want to provide support for the GNU gettext
++dnl functionality.
++dnl Please note that the actual code of the GNU gettext library is covered
++dnl by the GNU Lesser General Public License, and the rest of the GNU
++dnl gettext package is covered by the GNU General Public License.
++dnl They are *not* in the public domain.
++
++dnl Authors:
++dnl Ulrich Drepper <drepper@cygnus.com>, 1996.
++
++AC_PREREQ([2.53])
++
++# Search path for a program which passes the given test.
++
++dnl AM_PATH_PROG_WITH_TEST(VARIABLE, PROG-TO-CHECK-FOR,
++dnl TEST-PERFORMED-ON-FOUND_PROGRAM [, VALUE-IF-NOT-FOUND [, PATH]])
++AC_DEFUN([AM_PATH_PROG_WITH_TEST],
++[
++# Prepare PATH_SEPARATOR.
++# The user is always right.
++if test "${PATH_SEPARATOR+set}" != set; then
++ # Determine PATH_SEPARATOR by trying to find /bin/sh in a PATH which
++ # contains only /bin. Note that ksh looks also at the FPATH variable,
++ # so we have to set that as well for the test.
++ PATH_SEPARATOR=:
++ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 \
++ && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 \
++ || PATH_SEPARATOR=';'
++ }
++fi
++
++# Find out how to test for executable files. Don't use a zero-byte file,
++# as systems may use methods other than mode bits to determine executability.
++cat >conf$$.file <<_ASEOF
++#! /bin/sh
++exit 0
++_ASEOF
++chmod +x conf$$.file
++if test -x conf$$.file >/dev/null 2>&1; then
++ ac_executable_p="test -x"
++else
++ ac_executable_p="test -f"
++fi
++rm -f conf$$.file
++
++# Extract the first word of "$2", so it can be a program name with args.
++set dummy $2; ac_word=[$]2
++AC_MSG_CHECKING([for $ac_word])
++AC_CACHE_VAL([ac_cv_path_$1],
++[case "[$]$1" in
++ [[\\/]]* | ?:[[\\/]]*)
++ ac_cv_path_$1="[$]$1" # Let the user override the test with a path.
++ ;;
++ *)
++ ac_save_IFS="$IFS"; IFS=$PATH_SEPARATOR
++ for ac_dir in m4_if([$5], , $PATH, [$5]); do
++ IFS="$ac_save_IFS"
++ test -z "$ac_dir" && ac_dir=.
++ for ac_exec_ext in '' $ac_executable_extensions; do
++ if $ac_executable_p "$ac_dir/$ac_word$ac_exec_ext"; then
++ echo "$as_me: trying $ac_dir/$ac_word..." >&AS_MESSAGE_LOG_FD
++ if [$3]; then
++ ac_cv_path_$1="$ac_dir/$ac_word$ac_exec_ext"
++ break 2
++ fi
++ fi
++ done
++ done
++ IFS="$ac_save_IFS"
++dnl If no 4th arg is given, leave the cache variable unset,
++dnl so AC_PATH_PROGS will keep looking.
++m4_if([$4], , , [ test -z "[$]ac_cv_path_$1" && ac_cv_path_$1="$4"
++])dnl
++ ;;
++esac])dnl
++$1="$ac_cv_path_$1"
++if test m4_if([$4], , [-n "[$]$1"], ["[$]$1" != "$4"]); then
++ AC_MSG_RESULT([$][$1])
++else
++ AC_MSG_RESULT([no])
++fi
++AC_SUBST([$1])dnl
++])
++
++# Copyright (C) 2002-2021 Free Software Foundation, Inc.
+ #
+ # This file is free software; the Free Software Foundation
+ # gives unlimited permission to copy and/or distribute it,
+@@ -32,10 +10016,10 @@ To do so, use the procedure documented by the package, typically 'autoreconf'.])
+ # generated from the m4 files accompanying Automake X.Y.
+ # (This private macro should not be called outside this file.)
+ AC_DEFUN([AM_AUTOMAKE_VERSION],
+-[am__api_version='1.15'
++[am__api_version='1.16'
+ dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
+ dnl require some minimum version. Point them to the right macro.
+-m4_if([$1], [1.15.1], [],
++m4_if([$1], [1.16.5], [],
+ [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
+ ])
+
+@@ -51,14 +10035,14 @@ m4_define([_AM_AUTOCONF_VERSION], [])
+ # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
+ # This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
+ AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
+-[AM_AUTOMAKE_VERSION([1.15.1])dnl
++[AM_AUTOMAKE_VERSION([1.16.5])dnl
+ m4_ifndef([AC_AUTOCONF_VERSION],
+ [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+ _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
+
+ # AM_AUX_DIR_EXPAND -*- Autoconf -*-
+
+-# Copyright (C) 2001-2017 Free Software Foundation, Inc.
++# Copyright (C) 2001-2021 Free Software Foundation, Inc.
+ #
+ # This file is free software; the Free Software Foundation
+ # gives unlimited permission to copy and/or distribute it,
+@@ -110,7 +10094,7 @@ am_aux_dir=`cd "$ac_aux_dir" && pwd`
+
+ # AM_CONDITIONAL -*- Autoconf -*-
+
+-# Copyright (C) 1997-2017 Free Software Foundation, Inc.
++# Copyright (C) 1997-2021 Free Software Foundation, Inc.
+ #
+ # This file is free software; the Free Software Foundation
+ # gives unlimited permission to copy and/or distribute it,
+@@ -141,7 +10125,7 @@ AC_CONFIG_COMMANDS_PRE(
+ Usually this means the macro was only invoked conditionally.]])
+ fi])])
+
+-# Copyright (C) 1999-2017 Free Software Foundation, Inc.
++# Copyright (C) 1999-2021 Free Software Foundation, Inc.
+ #
+ # This file is free software; the Free Software Foundation
+ # gives unlimited permission to copy and/or distribute it,
+@@ -332,13 +10316,12 @@ _AM_SUBST_NOTMAKE([am__nodep])dnl
+
+ # Generate code to set up dependency tracking. -*- Autoconf -*-
+
+-# Copyright (C) 1999-2017 Free Software Foundation, Inc.
++# Copyright (C) 1999-2021 Free Software Foundation, Inc.
+ #
+ # This file is free software; the Free Software Foundation
+ # gives unlimited permission to copy and/or distribute it,
+ # with or without modifications, as long as this notice is preserved.
+
+-
+ # _AM_OUTPUT_DEPENDENCY_COMMANDS
+ # ------------------------------
+ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
+@@ -346,49 +10329,43 @@ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
+ # Older Autoconf quotes --file arguments for eval, but not when files
+ # are listed without --file. Let's play safe and only enable the eval
+ # if we detect the quoting.
+- case $CONFIG_FILES in
+- *\'*) eval set x "$CONFIG_FILES" ;;
+- *) set x $CONFIG_FILES ;;
+- esac
++ # TODO: see whether this extra hack can be removed once we start
++ # requiring Autoconf 2.70 or later.
++ AS_CASE([$CONFIG_FILES],
++ [*\'*], [eval set x "$CONFIG_FILES"],
++ [*], [set x $CONFIG_FILES])
+ shift
+- for mf
++ # Used to flag and report bootstrapping failures.
++ am_rc=0
++ for am_mf
+ do
+ # Strip MF so we end up with the name of the file.
+- mf=`echo "$mf" | sed -e 's/:.*$//'`
+- # Check whether this is an Automake generated Makefile or not.
+- # We used to match only the files named 'Makefile.in', but
+- # some people rename them; so instead we look at the file content.
+- # Grep'ing the first line is not enough: some people post-process
+- # each Makefile.in and add a new line on top of each file to say so.
+- # Grep'ing the whole file is not good either: AIX grep has a line
++ am_mf=`AS_ECHO(["$am_mf"]) | sed -e 's/:.*$//'`
++ # Check whether this is an Automake generated Makefile which includes
++ # dependency-tracking related rules and includes.
++ # Grep'ing the whole file directly is not great: AIX grep has a line
+ # limit of 2048, but all sed's we know have understand at least 4000.
+- if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
+- dirpart=`AS_DIRNAME("$mf")`
+- else
+- continue
+- fi
+- # Extract the definition of DEPDIR, am__include, and am__quote
+- # from the Makefile without running 'make'.
+- DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+- test -z "$DEPDIR" && continue
+- am__include=`sed -n 's/^am__include = //p' < "$mf"`
+- test -z "$am__include" && continue
+- am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+- # Find all dependency output files, they are included files with
+- # $(DEPDIR) in their names. We invoke sed twice because it is the
+- # simplest approach to changing $(DEPDIR) to its actual value in the
+- # expansion.
+- for file in `sed -n "
+- s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+- sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do
+- # Make sure the directory exists.
+- test -f "$dirpart/$file" && continue
+- fdir=`AS_DIRNAME(["$file"])`
+- AS_MKDIR_P([$dirpart/$fdir])
+- # echo "creating $dirpart/$file"
+- echo '# dummy' > "$dirpart/$file"
+- done
++ sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \
++ || continue
++ am_dirpart=`AS_DIRNAME(["$am_mf"])`
++ am_filepart=`AS_BASENAME(["$am_mf"])`
++ AM_RUN_LOG([cd "$am_dirpart" \
++ && sed -e '/# am--include-marker/d' "$am_filepart" \
++ | $MAKE -f - am--depfiles]) || am_rc=$?
+ done
++ if test $am_rc -ne 0; then
++ AC_MSG_FAILURE([Something went wrong bootstrapping makefile fragments
++ for automatic dependency tracking. If GNU make was not used, consider
++ re-running the configure script with MAKE="gmake" (or whatever is
++ necessary). You can also try re-running configure with the
++ '--disable-dependency-tracking' option to at least be able to build
++ the package (albeit without support for automatic dependency tracking).])
++ fi
++ AS_UNSET([am_dirpart])
++ AS_UNSET([am_filepart])
++ AS_UNSET([am_mf])
++ AS_UNSET([am_rc])
++ rm -f conftest-deps.mk
+ }
+ ])# _AM_OUTPUT_DEPENDENCY_COMMANDS
+
+@@ -397,18 +10374,17 @@ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
+ # -----------------------------
+ # This macro should only be invoked once -- use via AC_REQUIRE.
+ #
+-# This code is only required when automatic dependency tracking
+-# is enabled. FIXME. This creates each '.P' file that we will
+-# need in order to bootstrap the dependency handling code.
++# This code is only required when automatic dependency tracking is enabled.
++# This creates each '.Po' and '.Plo' makefile fragment that we'll need in
++# order to bootstrap the dependency handling code.
+ AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
+ [AC_CONFIG_COMMANDS([depfiles],
+ [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS],
+- [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"])
+-])
++ [AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}"])])
+
+ # Do all the work for Automake. -*- Autoconf -*-
+
+-# Copyright (C) 1996-2017 Free Software Foundation, Inc.
++# Copyright (C) 1996-2021 Free Software Foundation, Inc.
+ #
+ # This file is free software; the Free Software Foundation
+ # gives unlimited permission to copy and/or distribute it,
+@@ -436,6 +10412,10 @@ m4_defn([AC_PROG_CC])
+ # release and drop the old call support.
+ AC_DEFUN([AM_INIT_AUTOMAKE],
+ [AC_PREREQ([2.65])dnl
++m4_ifdef([_$0_ALREADY_INIT],
++ [m4_fatal([$0 expanded multiple times
++]m4_defn([_$0_ALREADY_INIT]))],
++ [m4_define([_$0_ALREADY_INIT], m4_expansion_stack)])dnl
+ dnl Autoconf wants to disallow AM_ names. We explicitly allow
+ dnl the ones we care about.
+ m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
+@@ -472,7 +10452,7 @@ m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
+ [_AM_SET_OPTIONS([$1])dnl
+ dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT.
+ m4_if(
+- m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]),
++ m4_ifset([AC_PACKAGE_NAME], [ok]):m4_ifset([AC_PACKAGE_VERSION], [ok]),
+ [ok:ok],,
+ [m4_fatal([AC_INIT should be called with package and version arguments])])dnl
+ AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
+@@ -495,8 +10475,8 @@ AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl
+ AC_REQUIRE([AC_PROG_MKDIR_P])dnl
+ # For better backward compatibility. To be removed once Automake 1.9.x
+ # dies out for good. For more background, see:
+-# <http://lists.gnu.org/archive/html/automake/2012-07/msg00001.html>
+-# <http://lists.gnu.org/archive/html/automake/2012-07/msg00014.html>
++# <https://lists.gnu.org/archive/html/automake/2012-07/msg00001.html>
++# <https://lists.gnu.org/archive/html/automake/2012-07/msg00014.html>
+ AC_SUBST([mkdir_p], ['$(MKDIR_P)'])
+ # We need awk for the "check" target (and possibly the TAP driver). The
+ # system "awk" is bad on some platforms.
+@@ -524,6 +10504,20 @@ AC_PROVIDE_IFELSE([AC_PROG_OBJCXX],
+ [m4_define([AC_PROG_OBJCXX],
+ m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl
+ ])
++# Variables for tags utilities; see am/tags.am
++if test -z "$CTAGS"; then
++ CTAGS=ctags
++fi
++AC_SUBST([CTAGS])
++if test -z "$ETAGS"; then
++ ETAGS=etags
++fi
++AC_SUBST([ETAGS])
++if test -z "$CSCOPE"; then
++ CSCOPE=cscope
++fi
++AC_SUBST([CSCOPE])
++
+ AC_REQUIRE([AM_SILENT_RULES])dnl
+ dnl The testsuite driver may need to know about EXEEXT, so add the
+ dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This
+@@ -563,7 +10557,7 @@ END
+ Aborting the configuration process, to ensure you take notice of the issue.
+
+ You can download and install GNU coreutils to get an 'rm' implementation
+-that behaves properly: <http://www.gnu.org/software/coreutils/>.
++that behaves properly: <https://www.gnu.org/software/coreutils/>.
+
+ If you want to complete the configuration process using your problematic
+ 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM
+@@ -605,7 +10599,7 @@ for _am_header in $config_headers :; do
+ done
+ echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
+
+-# Copyright (C) 2001-2017 Free Software Foundation, Inc.
++# Copyright (C) 2001-2021 Free Software Foundation, Inc.
+ #
+ # This file is free software; the Free Software Foundation
+ # gives unlimited permission to copy and/or distribute it,
+@@ -626,7 +10620,26 @@ if test x"${install_sh+set}" != xset; then
+ fi
+ AC_SUBST([install_sh])])
+
+-# Copyright (C) 1998-2017 Free Software Foundation, Inc.
++# Copyright (C) 2003-2021 Free Software Foundation, Inc.
++#
++# This file is free software; the Free Software Foundation
++# gives unlimited permission to copy and/or distribute it,
++# with or without modifications, as long as this notice is preserved.
++
++# Check whether the underlying file-system supports filenames
++# with a leading dot. For instance MS-DOS doesn't.
++AC_DEFUN([AM_SET_LEADING_DOT],
++[rm -rf .tst 2>/dev/null
++mkdir .tst 2>/dev/null
++if test -d .tst; then
++ am__leading_dot=.
++else
++ am__leading_dot=_
++fi
++rmdir .tst 2>/dev/null
++AC_SUBST([am__leading_dot])])
++
++# Copyright (C) 1998-2021 Free Software Foundation, Inc.
+ #
+ # This file is free software; the Free Software Foundation
+ # gives unlimited permission to copy and/or distribute it,
+@@ -647,7 +10660,7 @@ fi])
+ # Add --enable-maintainer-mode option to configure. -*- Autoconf -*-
+ # From Jim Meyering
+
+-# Copyright (C) 1996-2017 Free Software Foundation, Inc.
++# Copyright (C) 1996-2021 Free Software Foundation, Inc.
+ #
+ # This file is free software; the Free Software Foundation
+ # gives unlimited permission to copy and/or distribute it,
+@@ -682,7 +10695,7 @@ AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles])
+
+ # Check to see how 'make' treats includes. -*- Autoconf -*-
+
+-# Copyright (C) 2001-2017 Free Software Foundation, Inc.
++# Copyright (C) 2001-2021 Free Software Foundation, Inc.
+ #
+ # This file is free software; the Free Software Foundation
+ # gives unlimited permission to copy and/or distribute it,
+@@ -690,49 +10703,42 @@ AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles])
+
+ # AM_MAKE_INCLUDE()
+ # -----------------
+-# Check to see how make treats includes.
++# Check whether make has an 'include' directive that can support all
++# the idioms we need for our automatic dependency tracking code.
+ AC_DEFUN([AM_MAKE_INCLUDE],
+-[am_make=${MAKE-make}
+-cat > confinc << 'END'
++[AC_MSG_CHECKING([whether ${MAKE-make} supports the include directive])
++cat > confinc.mk << 'END'
+ am__doit:
+- @echo this is the am__doit target
++ @echo this is the am__doit target >confinc.out
+ .PHONY: am__doit
+ END
+-# If we don't find an include directive, just comment out the code.
+-AC_MSG_CHECKING([for style of include used by $am_make])
+ am__include="#"
+ am__quote=
+-_am_result=none
+-# First try GNU make style include.
+-echo "include confinc" > confmf
+-# Ignore all kinds of additional output from 'make'.
+-case `$am_make -s -f confmf 2> /dev/null` in #(
+-*the\ am__doit\ target*)
+- am__include=include
+- am__quote=
+- _am_result=GNU
+- ;;
+-esac
+-# Now try BSD make style include.
+-if test "$am__include" = "#"; then
+- echo '.include "confinc"' > confmf
+- case `$am_make -s -f confmf 2> /dev/null` in #(
+- *the\ am__doit\ target*)
+- am__include=.include
+- am__quote="\""
+- _am_result=BSD
+- ;;
+- esac
+-fi
+-AC_SUBST([am__include])
+-AC_SUBST([am__quote])
+-AC_MSG_RESULT([$_am_result])
+-rm -f confinc confmf
+-])
++# BSD make does it like this.
++echo '.include "confinc.mk" # ignored' > confmf.BSD
++# Other make implementations (GNU, Solaris 10, AIX) do it like this.
++echo 'include confinc.mk # ignored' > confmf.GNU
++_am_result=no
++for s in GNU BSD; do
++ AM_RUN_LOG([${MAKE-make} -f confmf.$s && cat confinc.out])
++ AS_CASE([$?:`cat confinc.out 2>/dev/null`],
++ ['0:this is the am__doit target'],
++ [AS_CASE([$s],
++ [BSD], [am__include='.include' am__quote='"'],
++ [am__include='include' am__quote=''])])
++ if test "$am__include" != "#"; then
++ _am_result="yes ($s style)"
++ break
++ fi
++done
++rm -f confinc.* confmf.*
++AC_MSG_RESULT([${_am_result}])
++AC_SUBST([am__include])])
++AC_SUBST([am__quote])])
+
+ # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*-
+
+-# Copyright (C) 1997-2017 Free Software Foundation, Inc.
++# Copyright (C) 1997-2021 Free Software Foundation, Inc.
+ #
+ # This file is free software; the Free Software Foundation
+ # gives unlimited permission to copy and/or distribute it,
+@@ -753,12 +10759,7 @@ AC_DEFUN([AM_MISSING_HAS_RUN],
+ [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+ AC_REQUIRE_AUX_FILE([missing])dnl
+ if test x"${MISSING+set}" != xset; then
+- case $am_aux_dir in
+- *\ * | *\ *)
+- MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
+- *)
+- MISSING="\${SHELL} $am_aux_dir/missing" ;;
+- esac
++ MISSING="\${SHELL} '$am_aux_dir/missing'"
+ fi
+ # Use eval to expand $SHELL
+ if eval "$MISSING --is-lightweight"; then
+@@ -771,7 +10772,7 @@ fi
+
+ # Helper functions for option handling. -*- Autoconf -*-
+
+-# Copyright (C) 2001-2017 Free Software Foundation, Inc.
++# Copyright (C) 2001-2021 Free Software Foundation, Inc.
+ #
+ # This file is free software; the Free Software Foundation
+ # gives unlimited permission to copy and/or distribute it,
+@@ -800,7 +10801,7 @@ AC_DEFUN([_AM_SET_OPTIONS],
+ AC_DEFUN([_AM_IF_OPTION],
+ [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
+
+-# Copyright (C) 1999-2017 Free Software Foundation, Inc.
++# Copyright (C) 1999-2021 Free Software Foundation, Inc.
+ #
+ # This file is free software; the Free Software Foundation
+ # gives unlimited permission to copy and/or distribute it,
+@@ -847,7 +10848,7 @@ AC_LANG_POP([C])])
+ # For backward compatibility.
+ AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])])
+
+-# Copyright (C) 2001-2017 Free Software Foundation, Inc.
++# Copyright (C) 2001-2021 Free Software Foundation, Inc.
+ #
+ # This file is free software; the Free Software Foundation
+ # gives unlimited permission to copy and/or distribute it,
+@@ -866,7 +10867,7 @@ AC_DEFUN([AM_RUN_LOG],
+
+ # Check to make sure that the build environment is sane. -*- Autoconf -*-
+
+-# Copyright (C) 1996-2017 Free Software Foundation, Inc.
++# Copyright (C) 1996-2021 Free Software Foundation, Inc.
+ #
+ # This file is free software; the Free Software Foundation
+ # gives unlimited permission to copy and/or distribute it,
+@@ -947,7 +10948,7 @@ AC_CONFIG_COMMANDS_PRE(
+ rm -f conftest.file
+ ])
+
+-# Copyright (C) 2009-2017 Free Software Foundation, Inc.
++# Copyright (C) 2009-2021 Free Software Foundation, Inc.
+ #
+ # This file is free software; the Free Software Foundation
+ # gives unlimited permission to copy and/or distribute it,
+@@ -1007,7 +11008,7 @@ AC_SUBST([AM_BACKSLASH])dnl
+ _AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl
+ ])
+
+-# Copyright (C) 2001-2017 Free Software Foundation, Inc.
++# Copyright (C) 2001-2021 Free Software Foundation, Inc.
+ #
+ # This file is free software; the Free Software Foundation
+ # gives unlimited permission to copy and/or distribute it,
+@@ -1035,7 +11036,7 @@ fi
+ INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+ AC_SUBST([INSTALL_STRIP_PROGRAM])])
+
+-# Copyright (C) 2006-2017 Free Software Foundation, Inc.
++# Copyright (C) 2006-2021 Free Software Foundation, Inc.
+ #
+ # This file is free software; the Free Software Foundation
+ # gives unlimited permission to copy and/or distribute it,
+@@ -1054,7 +11055,7 @@ AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
+
+ # Check how to create a tarball. -*- Autoconf -*-
+
+-# Copyright (C) 2004-2017 Free Software Foundation, Inc.
++# Copyright (C) 2004-2021 Free Software Foundation, Inc.
+ #
+ # This file is free software; the Free Software Foundation
+ # gives unlimited permission to copy and/or distribute it,
+@@ -1185,27 +11186,3 @@ AC_SUBST([am__tar])
+ AC_SUBST([am__untar])
+ ]) # _AM_PROG_TAR
+
+-m4_include([../bfd/acinclude.m4])
+-m4_include([../bfd/warning.m4])
+-m4_include([../config/acx.m4])
+-m4_include([../config/bfd64.m4])
+-m4_include([../config/depstand.m4])
+-m4_include([../config/enable.m4])
+-m4_include([../config/gettext-sister.m4])
+-m4_include([../config/jobserver.m4])
+-m4_include([../config/largefile.m4])
+-m4_include([../config/lcmessage.m4])
+-m4_include([../config/lead-dot.m4])
+-m4_include([../config/nls.m4])
+-m4_include([../config/override.m4])
+-m4_include([../config/pkg.m4])
+-m4_include([../config/plugins.m4])
+-m4_include([../config/po.m4])
+-m4_include([../config/progtest.m4])
+-m4_include([../config/zlib.m4])
+-m4_include([../config/zstd.m4])
+-m4_include([../libtool.m4])
+-m4_include([../ltoptions.m4])
+-m4_include([../ltsugar.m4])
+-m4_include([../ltversion.m4])
+-m4_include([../lt~obsolete.m4])
+diff --git a/ld/configure.tgt b/ld/configure.tgt
+index de04a44b..baceb2cc 100644
+--- a/ld/configure.tgt
++++ b/ld/configure.tgt
+@@ -81,6 +81,15 @@ fi
+ # Please try to keep this table more or less in alphabetic order - it
+ # makes it much easier to lookup a specific archictecture.
+ case "${targ}" in
++i[3-7]86-*-sb*)
++ targ_emul=elf_i386_sb
++ targ_extra_emuls=elf_i386
++# targ64_extra_emuls="elf_x86_64_sb_x86_64"
++ ;;
++#x86_64-*-sb*)
++# targ_emul=elf_x86_64_sb
++# targ_extra_emuls="elf_i386_sb elf_x86_64 elf_i386"
++# ;;
+ aarch64_be-*-elf) targ_emul=aarch64elfb
+ targ_extra_emuls="aarch64elf aarch64elf32 aarch64elf32b armelfb armelf"
+ ;;
+diff --git a/ld/emulparams/elf_i386_sb.sh b/ld/emulparams/elf_i386_sb.sh
+new file mode 100644
+index 00000000..06482257
+--- /dev/null
++++ b/ld/emulparams/elf_i386_sb.sh
+@@ -0,0 +1,2 @@
++source_sh ${srcdir}/emulparams/elf_i386.sh
++TEXT_START_ADDR=0x08000000
+diff --git a/ld/emulparams/elf_x86_64_sb.sh b/ld/emulparams/elf_x86_64_sb.sh
+new file mode 100644
+index 00000000..59e7df71
+--- /dev/null
++++ b/ld/emulparams/elf_x86_64_sb.sh
+@@ -0,0 +1 @@
++source_sh ${srcdir}/emulparams/elf_x86_64.sh
+diff --git a/ld/emulparams/elf_x86_64_sb_x86_64.sh b/ld/emulparams/elf_x86_64_sb_x86_64.sh
+new file mode 100644
+index 00000000..59e7df71
+--- /dev/null
++++ b/ld/emulparams/elf_x86_64_sb_x86_64.sh
+@@ -0,0 +1 @@
++source_sh ${srcdir}/emulparams/elf_x86_64.sh
diff --git a/toolchain/build-binutils.sh b/toolchain/build-binutils.sh
new file mode 100755
index 0000000..12bcde9
--- /dev/null
+++ b/toolchain/build-binutils.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+./download-binutils.sh
+tar -xf binutils*.tar.xz
+cd ./binutils-*/
+patch -f -p1 -i ../binutils-2.40.diff
+cd ..
+mkdir bin
+#PREFIX="/home/anton/prj/osdev/sysroot"
+PREFIX="$(pwd)/bin"
+mkdir build-binutils
+cd build-binutils
+../binutils*/configure --target=i686-sb --prefix="$PREFIX" --with-sysroot="/home/anton/prj/osdev/sysroot" --disable-werror
+make -j8 && make install
diff --git a/toolchain/build-gcc.sh b/toolchain/build-gcc.sh
new file mode 100755
index 0000000..c9af8a1
--- /dev/null
+++ b/toolchain/build-gcc.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+./download-gcc.sh
+tar -xf gcc-*.tar.xz
+cd ./gcc-*/
+patch -f -p1 -i ../gcc-13.1.0.diff
+cd ..
+mkdir bin
+PREFIX=$(pwd)"/bin"
+#PREFIX="/home/anton/prj/osdev/sysroot"
+mkdir build-gcc
+cd build-gcc
+../gcc-*/configure --target=i686-sb --prefix="$PREFIX" --with-gmp --with-mpfr --with-sysroot="/home/anton/prj/osdev/sysroot" --enable-languages=c,c++
+make -j6 all-gcc all-target-libgcc && make install-gcc install-target-libgcc
diff --git a/toolchain/download-binutils.sh b/toolchain/download-binutils.sh
new file mode 100755
index 0000000..4a72cf9
--- /dev/null
+++ b/toolchain/download-binutils.sh
@@ -0,0 +1,2 @@
+#!/bin/sh
+BIN="binutils-2.40.tar.xz" URL="https://ftp.gnu.org/gnu/binutils" ./download.sh
diff --git a/toolchain/download-gcc.sh b/toolchain/download-gcc.sh
new file mode 100755
index 0000000..a7e2c94
--- /dev/null
+++ b/toolchain/download-gcc.sh
@@ -0,0 +1,2 @@
+#!/bin/sh
+BIN="gcc-13.1.0.tar.xz" URL="https://ftp.gnu.org/gnu/gcc/gcc-13.1.0" ./download.sh
diff --git a/toolchain/download.sh b/toolchain/download.sh
new file mode 100755
index 0000000..770e812
--- /dev/null
+++ b/toolchain/download.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+[ -f "$BIN.sig" ] && gpg --verify $BIN.sig $BIN && exit 0
+[ -f "$BIN.sig" ] || wget "$URL/$BIN.sig"
+[ -f "$BIN" ] && gpg --verify $BIN.sig $BIN && exit 0
+wget "$URL/$BIN"
+gpg --verify $BIN.sig $BIN && exit 0
+rm $BIN
+echo "Signature failed"
+exit 1
diff --git a/toolchain/gcc-13.1.0.diff b/toolchain/gcc-13.1.0.diff
new file mode 100644
index 0000000..eb15a77
--- /dev/null
+++ b/toolchain/gcc-13.1.0.diff
@@ -0,0 +1,142 @@
+diff --git a/config.sub b/config.sub
+index 38f3d037a..44169ef44 100755
+--- a/config.sub
++++ b/config.sub
+@@ -1749,7 +1749,7 @@ case $os in
+ | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \
+ | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \
+ | nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr* \
+- | fiwix* )
++ | fiwix* | sb*)
+ ;;
+ # This one is extra strict with allowed versions
+ sco3.2v2 | sco3.2v[4-9]* | sco5v6*)
+diff --git a/fixincludes/mkfixinc.sh b/fixincludes/mkfixinc.sh
+index df90720b7..fdd219967 100755
+--- a/fixincludes/mkfixinc.sh
++++ b/fixincludes/mkfixinc.sh
+@@ -11,6 +11,8 @@ target=fixinc.sh
+
+ # Check for special fix rules for particular targets
+ case $machine in
++ *-sb* | \
++ *-*-sb* | \
+ i?86-*-cygwin* | \
+ i?86-*-mingw32* | \
+ x86_64-*-mingw32* | \
+diff --git a/gcc/config.gcc b/gcc/config.gcc
+index 6fd159448..c4c05ce9e 100644
+--- a/gcc/config.gcc
++++ b/gcc/config.gcc
+@@ -690,6 +690,12 @@ x86_cpus="generic intel"
+
+ # Common parts for widely ported systems.
+ case ${target} in
++*-*-sb*)
++ gas=yes
++ gnu_ld=yes
++ default_use_cxa_atexit=yes
++ use_gcc_stdint=provide
++ ;;
+ *-*-darwin*)
+ tmake_file="t-darwin "
+ tm_file="${tm_file} darwin.h"
+@@ -1126,6 +1132,9 @@ case ${target} in
+ esac
+
+ case ${target} in
++#i[34567]86-*-sb*) # UNSURE
++# tm_file="${tm_file} i386/unix.h i386/att.h elfos.h glibc-stdint.h i386/i386elf.h sb.h"
++# ;;
+ aarch64*-*-elf | aarch64*-*-fuchsia* | aarch64*-*-rtems*)
+ tm_file="${tm_file} elfos.h newlib-stdint.h"
+ tm_file="${tm_file} aarch64/aarch64-elf.h aarch64/aarch64-errata.h aarch64/aarch64-elf-raw.h"
+@@ -2327,6 +2336,10 @@ m68k-*-elf* | fido-*-elf*)
+ ;;
+ esac
+ ;;
++#AAAAAAAAAAAAAAAAAAA
++i[34567]86-*-sb*) # UNSURE
++ tm_file="${tm_file} i386/unix.h i386/att.h elfos.h glibc-stdint.h i386/i386elf.h sb.h"
++ ;;
+ m68k*-*-netbsdelf*)
+ default_m68k_cpu=68020
+ default_cf_cpu=5475
+diff --git a/gcc/config/sb.h b/gcc/config/sb.h
+new file mode 100644
+index 000000000..b721cb53f
+--- /dev/null
++++ b/gcc/config/sb.h
+@@ -0,0 +1,28 @@
++/* Useful if you wish to make target-specific GCC changes. */
++#undef TARGET_SB
++#define TARGET_SB 1
++
++/* Default arguments you want when running your
++ i686-myos-gcc/x86_64-myos-gcc toolchain */
++#undef LIB_SPEC
++#define LIB_SPEC "-lc" /* link against C standard library */
++
++/* Files that are linked before user code.
++ The %s tells GCC to look for these files in the library directory. */
++#undef STARTFILE_SPEC
++#define STARTFILE_SPEC "crt0.o%s crti.o%s crtbegin.o%s"
++
++/* Files that are linked after user code. */
++#undef ENDFILE_SPEC
++#define ENDFILE_SPEC "crtend.o%s crtn.o%s"
++
++/* Additional predefined macros. */
++#undef TARGET_OS_CPP_BUILTINS
++#define TARGET_OS_CPP_BUILTINS() \
++ do { \
++ builtin_define("__sb__"); \
++ builtin_define("__unix__"); \
++ builtin_assert("system=sb"); \
++ builtin_assert("system=unix"); \
++ builtin_assert("system=posix"); \
++ } while (0);
+diff --git a/libgcc/config.host b/libgcc/config.host
+index b9975de90..da9323956 100644
+--- a/libgcc/config.host
++++ b/libgcc/config.host
+@@ -220,6 +220,10 @@ esac
+
+ # Common parts for widely ported systems.
+ case ${host} in
++#i[34567]86-*-sb*)
++# extra_parts="$extra_parts crti.o crtbegin.o crtend.o crtn.o"
++# tmake_file="$tmake_file i386/t-crtstuff t-crtstuff-pic t-libgcc-pic"
++# ;;
+ *-*-darwin*)
+ asm_hidden_op=.private_extern
+ tmake_file="$tmake_file t-darwin ${cpu_type}/t-darwin t-libgcc-pic"
+@@ -1503,6 +1507,10 @@ am33_2.0-*-linux*)
+ m32c-*-elf*)
+ tmake_file="$tmake_file m32c/t-m32c"
+ ;;
++i[34567]86-*-sb*)
++ extra_parts="$extra_parts crti.o crtbegin.o crtend.o crtn.o"
++ tmake_file="$tmake_file i386/t-crtstuff t-crtstuff-pic t-libgcc-pic"
++ ;;
+ nvptx-*)
+ tmake_file="$tmake_file nvptx/t-nvptx"
+ extra_parts="crt0.o"
+diff --git a/libstdc++-v3/crossconfig.m4 b/libstdc++-v3/crossconfig.m4
+index b3269cb88..8c0bc1e6f 100644
+--- a/libstdc++-v3/crossconfig.m4
++++ b/libstdc++-v3/crossconfig.m4
+@@ -8,7 +8,12 @@ case "${host}" in
+ arm*-*-symbianelf*)
+ # This is a freestanding configuration; there is nothing to do here.
+ ;;
+-
++ *-sb*)
++ GLIBCXX_CHECK_COMPILER_FEATURES
++ GLIBCXX_CHECK_LINKER_FEATURES
++ GLIBCXX_CHECK_MATH_SUPPORT
++ GLIBCXX_CHECK_STDLIB_SUPPORT
++ ;;
+ avr*-*-*)
+ AC_DEFINE(HAVE_ACOSF)
+ AC_DEFINE(HAVE_ASINF)
diff --git a/toolchain/get-keys.sh b/toolchain/get-keys.sh
new file mode 100755
index 0000000..0210b8f
--- /dev/null
+++ b/toolchain/get-keys.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+gpg --recv-key 3A24BC1E8FB409FA9F14371813FCEF89DD9E3C4F
+gpg --recv-key D3A93CAD751C2AF4F8C7AD516C35B99309B5FA62
diff --git a/userland/ante/Makefile b/userland/ante/Makefile
new file mode 100644
index 0000000..412b302
--- /dev/null
+++ b/userland/ante/Makefile
@@ -0,0 +1,15 @@
+CC="/home/anton/prj/osdev/sysroot/bin/i686-sb-gcc"
+CFLAGS = -ggdb -O2 -Wall -Wextra -pedantic -static
+LIB=-L../libgui -lgui -lgcc
+INC=-I../libgui/
+BINS=ante
+all: $(BINS)
+
+ante.o: ante.c
+ $(CC) $(CFLAGS) $(INC) $(LIB) -o $@ -c $<
+
+ante: ante.o
+ $(CC) $(CFLAGS) -o $@ $^ $(LIB)
+
+clean:
+ rm $(BINS) *.o
diff --git a/userland/ante/ante.c b/userland/ante/ante.c
new file mode 100644
index 0000000..753e7f2
--- /dev/null
+++ b/userland/ante/ante.c
@@ -0,0 +1,296 @@
+#include <assert.h>
+#include <fcntl.h>
+#include <libgui.h>
+#include <poll.h>
+#include <pty.h>
+#include <socket.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define BACKGROUND_COLOR 0x000000
+
+int file_fd;
+char *file_buffer;
+uint64_t file_buffer_size;
+uint64_t file_size = 0;
+uint64_t file_real_position = 0;
+GUI_Window *global_w;
+
+typedef enum {
+ NORMAL,
+ INSERT,
+ COMMAND,
+} editor_mode_t;
+
+editor_mode_t current_mode = NORMAL;
+uint32_t cursor_pos_x = 0;
+uint64_t cursor_pos_y = 0;
+void draw_file(void);
+void write_file(void);
+
+int clamp(int *x, int *y) {
+ int clamped = 0;
+ if (*x < 0) {
+ *x = 0;
+ clamped = 1;
+ }
+ if (*y < 0) {
+ *y = 0;
+ clamped = 1;
+ }
+ if (*x + 8 > global_w->sx) {
+ *x = (global_w->sx - 8) / 8;
+ clamped = 1;
+ }
+ if (*y + 8 > global_w->sy) {
+ *y = (global_w->sy - 8) / 8;
+ clamped = 1;
+ }
+ return clamped;
+}
+
+void insert_char(int pos, char c) {
+ if (0 == file_size) {
+ file_size++;
+ file_buffer[0] = c;
+ return;
+ }
+
+ // Shift the buffer at 'pos' to the right by one.
+ memmove(file_buffer + pos + 1, file_buffer + pos, file_size - pos);
+
+ file_buffer[pos] = c;
+ file_size++;
+}
+
+void delete_char(int pos, int *deleted_newline) {
+ if (0 == pos) {
+ return;
+ }
+ // Delete the characther at 'pos'. This makes sense if 'pos' is
+ // at the end of the file and as a result the shift operation done
+ // later in the function is not overwritting the characther.
+ if ('\n' == file_buffer[pos - 1])
+ *deleted_newline = 1;
+ file_buffer[pos - 1] = 0;
+
+ // Shift the buffer at 'pos' to the left by one
+ memmove(file_buffer + pos - 1, file_buffer + pos, file_size - pos);
+ file_size--;
+}
+
+uint64_t cursor_to_real(int x, int y, int *is_valid) {
+ *is_valid = 0;
+ if (clamp(&x, &y))
+ return file_real_position;
+ if (0 == file_size) {
+ if (0 == x && 0 == y) {
+ *is_valid = 1;
+ return 0;
+ }
+ return 0;
+ }
+ uint64_t p = 0;
+ int cx = 0;
+ int cy = 0;
+ for (; p < file_size; p++) {
+ if (cx == x && cy == y) {
+ *is_valid = 1;
+ break;
+ }
+ if ('\n' == file_buffer[p]) {
+ cx = 0;
+ cy++;
+ continue;
+ }
+ cx++;
+ }
+ if (*is_valid)
+ return p;
+ else
+ return file_real_position;
+}
+
+void key_event(char c) {
+ int x = 0;
+ int y = 0;
+ if (COMMAND == current_mode) {
+ if ('w' == c) {
+ printf("wrote to file\n");
+ write_file();
+ current_mode = NORMAL;
+ return;
+ }
+ if ('q' == c) {
+ close(file_fd);
+ close(global_w->ws_socket);
+ current_mode = NORMAL;
+ exit(0);
+ return;
+ }
+ return;
+ } else if (NORMAL == current_mode) {
+ switch (c) {
+ case 'j':
+ y++;
+ break;
+ case 'k':
+ y--;
+ break;
+ case 'l':
+ x++;
+ break;
+ case 'h':
+ x--;
+ break;
+ case 'c':
+ printf("entering command mode\n");
+ current_mode = COMMAND;
+ return;
+ break;
+ case 'i':
+ current_mode = INSERT;
+ return;
+ break;
+ default:
+ return;
+ }
+ } else {
+ if ('\x1B' == c) {
+ current_mode = NORMAL;
+ return;
+ }
+ if ('\b' == c) {
+ int deleted_newline = 0;
+ delete_char(file_real_position, &deleted_newline);
+ if (deleted_newline) {
+ y--;
+ } else {
+ x--;
+ }
+ GUI_ClearScreen(global_w, BACKGROUND_COLOR);
+ } else {
+ insert_char(file_real_position, c);
+ printf("inserting char: %c\n", c);
+ if ('\n' == c) {
+ cursor_pos_x = 0;
+ y++;
+ } else {
+ x++;
+ }
+ GUI_ClearScreen(global_w, BACKGROUND_COLOR);
+ }
+ }
+
+ int is_valid_position = 0;
+ file_real_position =
+ cursor_to_real(cursor_pos_x + x, cursor_pos_y + y, &is_valid_position);
+ if (!is_valid_position) {
+ return;
+ }
+ GUI_OverwriteFont(global_w, cursor_pos_x * 8, cursor_pos_y * 8,
+ BACKGROUND_COLOR);
+ draw_file();
+ cursor_pos_x += x;
+ cursor_pos_y += y;
+ GUI_OverwriteFont(global_w, cursor_pos_x * 8, cursor_pos_y * 8, 0xFFFFFF);
+
+ GUI_UpdateWindow(global_w);
+}
+
+void draw_file(void) {
+ assert(file_buffer);
+ uint32_t screen_pos_x = 0;
+ uint64_t screen_pos_y = 0;
+ for (uint64_t i = 0; i < file_size; i++) {
+ char c = file_buffer[i];
+ if ('\n' == c) {
+ screen_pos_x = 0;
+ screen_pos_y += 8;
+ continue;
+ }
+ GUI_DrawFont(global_w, screen_pos_x, screen_pos_y, c);
+ screen_pos_x += 8;
+ }
+}
+
+void write_file(void) {
+ assert(file_buffer);
+ pwrite(file_fd, file_buffer, file_size, 0);
+}
+
+int open_file(const char *file) {
+ file_fd = open(file, O_RDWR, O_CREAT);
+ printf("file_fd: %d\n", file_fd);
+ if (0 > file_fd) {
+ perror("open");
+ return 0;
+ }
+
+ file_buffer_size = 0x1000;
+ file_buffer = malloc(file_buffer_size);
+ uint64_t index = 0;
+ assert(file_buffer);
+ for (;;) {
+ char buffer[4096];
+ int rc = read(file_fd, buffer, 4096);
+ if (-1 == rc) {
+ perror("read");
+ assert(0);
+ }
+
+ if (0 == rc)
+ break;
+
+ file_size += rc;
+ if (file_size > file_buffer_size) {
+ file_buffer_size = file_size;
+ file_buffer = realloc(file_buffer, file_buffer_size);
+ assert(file_buffer);
+ }
+
+ for (int i = 0; i < rc; i++, index++) {
+ file_buffer[index] = buffer[i];
+ }
+ }
+ return 1;
+}
+
+void run() {
+ struct pollfd fds[1];
+ fds[0].fd = global_w->ws_socket;
+ fds[0].events = POLLIN;
+ fds[0].revents = 0;
+ for (;; fds[0].revents = 0) {
+ poll(fds, 1, 0);
+ if (fds[0].revents & POLLIN) {
+ WS_EVENT e;
+ int rc;
+ if (0 >= (rc = read(global_w->ws_socket, &e, sizeof(e))))
+ continue;
+ if (0 == e.c)
+ continue;
+ key_event(e.c);
+ }
+ }
+}
+
+int main(int argc, char **argv) {
+ if (argc < 2) {
+ printf("File has to be specified.\n");
+ return 1;
+ }
+ global_w = GUI_CreateWindow(10, 10, 150 * 4, 150 * 4);
+ assert(global_w);
+ GUI_ClearScreen(global_w, BACKGROUND_COLOR);
+ GUI_UpdateWindow(global_w);
+
+ assert(open_file(argv[1]));
+ draw_file();
+ run();
+ return 0;
+}
diff --git a/userland/cat/Makefile b/userland/cat/Makefile
new file mode 100644
index 0000000..b45fae9
--- /dev/null
+++ b/userland/cat/Makefile
@@ -0,0 +1,10 @@
+CC="/home/anton/opt/cross/bin/i686-elf-gcc"
+CFLAGS = -ggdb -ffreestanding -O0 -Wall -Wextra -pedantic -mgeneral-regs-only -Wimplicit-fallthrough
+BINS=cat
+all: $(BINS)
+
+cat.o: cat.c
+ $(CC) $(CFLAGS) -L../libc/ -lc -c cat.c -I../libc/
+
+cat: cat.o
+ $(CC) -shared -o cat -ffreestanding -nostdlib $(CFLAGS) cat.o -L../libc/ -lc -lgcc #-L../libc/c.a
diff --git a/userland/cat/cat b/userland/cat/cat
new file mode 100755
index 0000000..2ba0c4d
--- /dev/null
+++ b/userland/cat/cat
Binary files differ
diff --git a/userland/cat/cat.c b/userland/cat/cat.c
new file mode 100644
index 0000000..b143581
--- /dev/null
+++ b/userland/cat/cat.c
@@ -0,0 +1,24 @@
+#include <fcntl.h>
+#include <stdio.h>
+#include <dirent.h>
+
+int main(int argc, char **argv) {
+ DIR *d = opendir("/");
+ struct dirent *de = readdir(d);
+ printf("x : %x\n", de->d_name[0]);
+ for (;;)
+ ;
+ /*
+ int fd = 0;
+ if (argc < 2)
+ goto read_stdin;
+ for (int i = 1; i < argc; i++) {
+ if ((fd = open(argv[i], O_RDONLY, 0)) == -1) {
+ return 1;
+ }
+ read_stdin:
+ for (char c[4096], int rc; (rc = read(fd, c, 4096) > 0);)
+ write(1, c, rc);
+ }*/
+ return 0;
+}
diff --git a/userland/init/Makefile b/userland/init/Makefile
new file mode 100644
index 0000000..932fcd3
--- /dev/null
+++ b/userland/init/Makefile
@@ -0,0 +1,10 @@
+CC="/home/anton/opt/cross/bin/i686-elf-gcc"
+CFLAGS = -ggdb -ffreestanding -O0 -Wall -Wextra -pedantic -mgeneral-regs-only -Wimplicit-fallthrough
+BINS=init
+all: $(BINS)
+
+init.o: init.c
+ $(CC) $(CFLAGS) -I../libc/ -L../libc/ -lc -c init.c
+
+init: init.o
+ $(CC) -shared -o init -ffreestanding -nostdlib $(CFLAGS) init.o -L../libc/ -lc -lgcc #-L../libc/c.a
diff --git a/userland/init/crt0_old.c b/userland/init/crt0_old.c
new file mode 100644
index 0000000..7d1e977
--- /dev/null
+++ b/userland/init/crt0_old.c
@@ -0,0 +1,12 @@
+#include <stdint.h>
+int main(int argc, char **argv);
+//int main();
+
+void _start(int a, int b, int argc, char** argv)
+{
+ (void)a;
+ kprintf("argc : %x\n", &argc);
+ kprintf("argv : %x\n", &argv);
+ for(;;);
+// main(argc, t);
+}
diff --git a/userland/init/init b/userland/init/init
new file mode 100755
index 0000000..3ae9020
--- /dev/null
+++ b/userland/init/init
Binary files differ
diff --git a/userland/init/init.c b/userland/init/init.c
new file mode 100644
index 0000000..78c4420
--- /dev/null
+++ b/userland/init/init.c
@@ -0,0 +1,15 @@
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <unistd.h>
+
+int main(void) {
+ if (fork())
+ for (;;)
+ wait(NULL);
+
+ char *a[] = {NULL};
+ execv("/term", a);
+ return 1;
+}
diff --git a/userland/json/Makefile b/userland/json/Makefile
new file mode 100644
index 0000000..9fcb567
--- /dev/null
+++ b/userland/json/Makefile
@@ -0,0 +1,18 @@
+#CC="/home/anton/opt/cross/bin/i686-elf-gcc"
+#AR="/home/anton/opt/cross/bin/i686-elf-ar"
+CC="/home/anton/prj/osdev/sysroot/bin/i686-sb-gcc"
+AR="/home/anton/prj/osdev/sysroot/bin/i686-sb-ar"
+CFLAGS = -O0 -Wall -Wextra -pedantic -Wimplicit-fallthrough -static -Wno-undef
+BINS=libjson.a
+all: $(BINS)
+LIBS=-L./hashmap -lhashmap
+OBJ=json.o
+
+json.o: json.c
+ $(CC) $(CFLAGS) $(LIBS) -c json.c
+
+libjson.a: $(OBJ)
+ $(AR) rcs libjson.a $^
+
+clean:
+ rm libjson.a json.o
diff --git a/userland/json/hashmap b/userland/json/hashmap
new file mode 160000
+Subproject 07dfe3b606e0d82b2e181b27344b5e4ce8849f3
diff --git a/userland/json/json.c b/userland/json/json.c
new file mode 100644
index 0000000..6449193
--- /dev/null
+++ b/userland/json/json.c
@@ -0,0 +1,360 @@
+//
+// Copyright (C) 2022 by Anton Kling <anton@kling.gg>
+//
+// SPDX-License-Identifier: BSD-2-Clause
+//
+#include "hashmap/hashmap.h"
+#include <assert.h>
+#include <math.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+typedef enum JSON_TYPE {
+ NONE,
+ STRING,
+ NUMBER,
+ OBJECT,
+ ARRAY, // FIXME
+ BOOL,
+ JSON_NULL,
+} JSON_TYPE;
+
+typedef struct JSON_ENTRY {
+ char *name;
+ JSON_TYPE type;
+ void *value;
+} JSON_ENTRY;
+
+typedef struct JSON_OBJECT {
+ size_t size;
+ JSON_ENTRY *entries;
+ HashMap *hash_indexes;
+} JSON_OBJECT;
+
+typedef struct JSON_CTX {
+ JSON_ENTRY global_object;
+} JSON_CTX;
+
+void JSON_Init(JSON_CTX *ctx) {
+ ctx->global_object.name = NULL;
+ ctx->global_object.type = OBJECT;
+ ctx->global_object.value = malloc(sizeof(JSON_OBJECT));
+ JSON_OBJECT *obj = ctx->global_object.value;
+ obj->size = 0;
+ obj->entries = NULL;
+}
+
+const char *skip_whitespace(const char *str) {
+ for (; *str; str++)
+ switch (*str) {
+ case ' ':
+ case '\t':
+ case '\n':
+ case '\r':
+ break;
+ default:
+ goto _exit;
+ }
+_exit:
+ return str;
+}
+
+char to_lower(char c) {
+ if (c <= 'Z')
+ return c | 32;
+ return c;
+}
+
+int low_strequ(const char *s1, const char *s2, size_t l) {
+ for (; 0 < l; l--, s2++, s1++) {
+ if (to_lower(*s2) != to_lower(*s1))
+ return 0;
+ }
+ return 1;
+}
+
+const char *find_name(const char *json, char *name_buffer, size_t buffer_len,
+ size_t *name_length, int *rc) {
+ *rc = 0;
+ json = skip_whitespace(json);
+ if ('"' != *json)
+ return json;
+
+ // This *can* be the name
+ json++;
+ const char *tmp = json;
+ for (; *tmp && '"' != *tmp; tmp++)
+ ;
+ if (!(*tmp && ':' == *(tmp + 1))) {
+ // Invalid name
+ // FIXME: Do something better than this.
+ assert(0);
+ }
+ // The name was found.
+ *rc = 1;
+ size_t str_len;
+ if (tmp == json)
+ str_len = 0;
+ else
+ str_len = (tmp - json - 1);
+ if (str_len + 1 > buffer_len) {
+ // JSON string is too long for the buffer
+ // FIXME: Do something better than this.
+ assert(0);
+ }
+ memcpy(name_buffer, json, str_len + 1);
+ name_buffer[str_len + 1] = '\0';
+ *name_length = str_len;
+ return tmp + 2;
+}
+
+const char *find_entry(const char *json, char *name_buffer, size_t buffer_len,
+ size_t *name_length, JSON_TYPE *entry_type, int *rc) {
+ *rc = 0;
+ json = skip_whitespace(json);
+ json = find_name(json, name_buffer, 4096, name_length, rc);
+ json = skip_whitespace(json);
+ switch (*json) {
+ case '{':
+ *entry_type = OBJECT;
+ break;
+ case '"':
+ *entry_type = STRING;
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ *entry_type = NUMBER;
+ break;
+ case '[':
+ *entry_type = ARRAY;
+ break;
+ case 'T':
+ case 'F':
+ case 't':
+ case 'f':
+ *entry_type = BOOL;
+ break;
+ case 'N':
+ case 'n':
+ *entry_type = JSON_NULL;
+ break;
+ case '}':
+ *rc = 2;
+ break;
+ default:
+ *entry_type = NONE;
+ break;
+ }
+ return json;
+}
+
+const char *extract_int(const char *json, uint32_t **value, int *rc) {
+ *value = malloc(sizeof(uint32_t));
+ *rc = 0;
+ json = skip_whitespace(json);
+ // FIXME: Do some checking to determine that this is a int.
+ **value = 0;
+ for (; *json && ',' != *json && '}' != *json;) {
+ **value *= 10;
+ **value += (uint32_t)(*json - '0');
+ json++;
+ json = skip_whitespace(json);
+ }
+ if ('\0' != *json)
+ *rc = 1;
+ return json;
+}
+
+const char *extract_string(const char *json, char **value, int *rc) {
+ *value = malloc(4096);
+ *rc = 0;
+ int escape = 0;
+ json++;
+ char *tmp = *value;
+ for (; *json; json++) {
+ if ('"' == *json && !escape)
+ break;
+ escape = 0;
+
+ if ('\\' == *json && !escape) {
+ escape = 1;
+ continue;
+ }
+ *tmp = *json;
+ tmp++;
+ }
+ *tmp = '\0';
+ if ('\0' != *json)
+ *rc = 1;
+ return json;
+}
+
+const char *extract_bool(const char *json, uint8_t **value, int *rc) {
+ *value = malloc(sizeof(uint8_t));
+ *rc = 0;
+ if (low_strequ(json, "true", 3)) {
+ **value = 1;
+ json += 4;
+ *rc = 1;
+ return json;
+ } else if (low_strequ(json, "false", 4)) {
+ **value = 0;
+ json += 5;
+ *rc = 1;
+ return json;
+ }
+ return json;
+}
+
+const char *extract_null(const char *json, uint8_t **value, int *rc) {
+ *value = malloc(sizeof(uint8_t));
+ *rc = 0;
+
+ if (low_strequ(json, "null", 3)) {
+ **value = 0;
+ json += 4;
+ *rc = 1;
+ return json;
+ }
+ return json;
+}
+
+void hashmap_free_value(char *key, void *value) {
+ (void)key;
+ free(value);
+}
+
+JSON_ENTRY *JSON_at(JSON_ENTRY *entry, size_t i);
+
+void JSON_Parse(JSON_CTX *ctx, const char *json) {
+ int rc;
+ char name_buffer[4096];
+ size_t name_length;
+ JSON_TYPE entry_type;
+ JSON_OBJECT *object_stack[64];
+ memset(object_stack, 0, sizeof(JSON_OBJECT *[64]));
+ size_t parent_num = 0;
+ object_stack[parent_num] = ctx->global_object.value;
+ object_stack[parent_num]->size = 0;
+
+ for (;; json++) {
+ json = find_entry(json, name_buffer, 4096, &name_length, &entry_type, &rc);
+ if ('\0' == *json)
+ return;
+
+ if (2 == rc) {
+ if (0 == parent_num)
+ return;
+ parent_num--;
+ json++;
+ json = skip_whitespace(json);
+ if (',' == *json)
+ json++;
+ continue;
+ }
+
+ if (NULL == object_stack[parent_num]->entries) {
+ object_stack[parent_num]->entries = malloc(sizeof(JSON_ENTRY[30]));
+ object_stack[parent_num]->size = 0;
+ object_stack[parent_num]->hash_indexes = hashmap_create(30);
+ }
+
+ size_t entry_num = object_stack[parent_num]->size;
+ object_stack[parent_num]->size++;
+
+ if (NULL == object_stack[parent_num]->entries) {
+ void *rc = object_stack[parent_num]->entries =
+ malloc(sizeof(JSON_ENTRY[30]));
+ object_stack[parent_num]->entries = rc;
+ object_stack[parent_num]->size = 0;
+ object_stack[parent_num]->hash_indexes = hashmap_create(30);
+ }
+ JSON_ENTRY *entry = &object_stack[parent_num]->entries[entry_num];
+ if (1 == rc) {
+ name_length++;
+ entry->name = malloc(name_length + 2);
+ memcpy(entry->name, name_buffer, name_length);
+ entry->name[name_length] = '\0';
+ size_t *b = malloc(sizeof(size_t));
+ *b = entry_num;
+ hashmap_add_entry(object_stack[parent_num]->hash_indexes, entry->name, b,
+ hashmap_free_value, 1);
+ } else {
+ entry->name = NULL;
+ }
+ entry->type = entry_type;
+ if (OBJECT == entry_type) {
+ entry->value = malloc(sizeof(JSON_OBJECT));
+ parent_num++;
+ object_stack[parent_num] = entry->value;
+ object_stack[parent_num]->entries = NULL;
+ continue;
+ } else if (NUMBER == entry_type) {
+ json = extract_int(json, (uint32_t **)&entry->value, &rc);
+ } else if (STRING == entry_type) {
+ json = extract_string(json, (char **)&entry->value, &rc);
+ } else if (BOOL == entry_type) {
+ json = extract_bool(json, (uint8_t **)&entry->value, &rc);
+ } else if (JSON_NULL == entry_type) {
+ json = extract_null(json, (uint8_t **)&entry->value, &rc);
+ }
+ json++;
+ }
+}
+
+JSON_ENTRY *JSON_at(JSON_ENTRY *entry, size_t i) {
+ if (OBJECT != entry->type)
+ return NULL;
+ return &((JSON_OBJECT *)(entry->value))->entries[i];
+}
+
+JSON_ENTRY *JSON_search_name(JSON_ENTRY *entry, char *name) {
+ if (OBJECT != entry->type)
+ return NULL;
+ size_t *i =
+ hashmap_get_entry(((JSON_OBJECT *)(entry->value))->hash_indexes, name);
+ if (!i)
+ return NULL;
+ return JSON_at(entry, *i);
+}
+
+void write_entry_content(int fd, size_t indent, JSON_ENTRY *entry) {
+#define PLACE_TABS \
+ { \
+ for (size_t i = 0; i < indent; i++) \
+ dprintf(fd, "\t"); \
+ }
+ PLACE_TABS
+ if (entry->name)
+ dprintf(fd, "\"%s\": ", entry->name);
+ if (OBJECT == entry->type) {
+ JSON_OBJECT *object = entry->value;
+ dprintf(fd, "{\n");
+ for (size_t i = 0; i < object->size; i++)
+ write_entry_content(fd, indent + 1, &object->entries[i]);
+ PLACE_TABS
+ dprintf(fd, "},\n");
+ } else if (NUMBER == entry->type)
+ dprintf(fd, "%d,\n", *(uint32_t *)entry->value);
+ else if (STRING == entry->type)
+ dprintf(fd, "\"%s\",\n", (char *)entry->value);
+ else if (BOOL == entry->type)
+ dprintf(fd, "%s,\n", ((*(uint8_t *)entry->value) ? "true" : "false"));
+ else if (JSON_NULL == entry->type)
+ dprintf(fd, "null,\n");
+}
+
+void JSON_extract_fd(JSON_CTX *ctx, int fd) {
+ JSON_ENTRY *entry = &ctx->global_object;
+ write_entry_content(fd, 0, &((JSON_OBJECT *)entry->value)->entries[0]);
+}
diff --git a/userland/json/json.h b/userland/json/json.h
new file mode 100644
index 0000000..642a878
--- /dev/null
+++ b/userland/json/json.h
@@ -0,0 +1,39 @@
+#ifndef JSON_H
+#define JSON_H
+#include "hashmap/hashmap.h"
+#include <stddef.h>
+#include <stdint.h>
+
+typedef enum JSON_TYPE {
+ NONE,
+ STRING,
+ NUMBER,
+ OBJECT,
+ ARRAY, // FIXME
+ BOOL,
+ JSON_NULL,
+} JSON_TYPE;
+
+typedef struct JSON_ENTRY {
+ char *name;
+ JSON_TYPE type;
+ void *value;
+} JSON_ENTRY;
+
+typedef struct JSON_OBJECT {
+ uint64_t size;
+ JSON_ENTRY *entries;
+ HashMap *hash_indexes;
+} JSON_OBJECT;
+
+typedef struct JSON_CTX {
+ JSON_ENTRY global_object;
+} JSON_CTX;
+
+void JSON_Init(JSON_CTX *ctx);
+void JSON_Parse(JSON_CTX *ctx, const char *json);
+void JSON_extract_fd(JSON_CTX *ctx, int whitespace, int fd);
+uint64_t JSON_extract_length(JSON_CTX *ctx, int whitespace);
+JSON_ENTRY *JSON_at(JSON_ENTRY *entry, uint64_t i);
+JSON_ENTRY *JSON_search_name(JSON_ENTRY *entry, char *name);
+#endif
diff --git a/userland/json/libjson.a b/userland/json/libjson.a
new file mode 100644
index 0000000..ca66650
--- /dev/null
+++ b/userland/json/libjson.a
Binary files differ
diff --git a/userland/libc/Makefile b/userland/libc/Makefile
new file mode 100644
index 0000000..98d81d4
--- /dev/null
+++ b/userland/libc/Makefile
@@ -0,0 +1,26 @@
+CC="/home/anton/prj/osdev/sysroot/bin/i686-sb-gcc"
+AR="/home/anton/prj/osdev/sysroot/bin/i686-sb-ar"
+AS="/home/anton/prj/osdev/sysroot/bin/i686-sb-as"
+#CFLAGS = -ggdb -ffreestanding -O0 -Wall -Wextra -pedantic -mgeneral-regs-only -Wimplicit-fallthrough -I./include/ -static -fsanitize=shift,signed-integer-overflow,bounds
+CFLAGS = -ggdb -ffreestanding -O2 -Wall -pedantic -Wimplicit-fallthrough -I./include/ -static
+#BINS=c.a libc.o crt0.o malloc.o pty.o mmap.o
+OBJ=crt0.o libc.o malloc/malloc.o pty.o sys/mman/mmap.o memset.o assert.o stdio/snprintf.o stdio/vfprintf.o string/memcpy.o string/memcmp.o string/strcmp.o ubsan.o string/strcpy.o isspace.o stdio/puts.o stdio/putchar.o dirent/opendir.o dirent/readdir.o dirent/closedir.o unistd/getopt.o dirent/scandir.o dirent/alphasort.o stdio/printf.o stdio/vdprintf.o stdio/vprintf.o stdio/dprintf.o stdio/vprintf.o string/strlen.o string/strnlen.o stdio/stdin.o stdio/stdout.o stdio/stderr.o stdio/getchar.o stdio/fgetc.o arpa/inet/htons.o arpa/inet/htonl.o stdio/fread.o stdio/fwrite.o stdio/fopen.o stdio/fclose.o stdio/fseek.o ctype/isascii.o stdio/fprintf.o stdlib/atoi.o stdlib/strtol.o ctype/toupper.o ctype/tolower.o string/strcat.o string/strchr.o string/sscanf.o sys/stat/stat.o stdlib/getenv.o string/strrchr.o stdio/ftell.o stdio/tmpfile.o stdio/fgets.o stdio/feof.o stdio/fscanf.o stdio/ungetc.o string/strncmp.o stdio/fputc.o string/strncpy.o stdio/remove.o stdio/ferror.o stdio/fputs.o stdlib/rand.o stdlib/srand.o unistd/getpid.o stdlib/strtoul.o stdio/fflush.o stdlib/abort.o string/strcspn.o time/localtime.o time/time.o time/clock_gettime.o time/gmtime.o time/strftime.o string/strpbrk.o ctype/isdigit.o ctype/isalpha.o ctype/isxdigit.o ctype/ispunct.o stdio/setvbuf.o stdio/fileno.o stdio/putc.o stdio/sprintf.o stdlib/abs.o string/strspn.o stdlib/qsort.o string/memmove.o setjmp/longjmp.o setjmp/setjmp.o libgen/basename.o string/strdup.o string/strndup.o string/strlcpy.o stdlib/atexit.o stdio/open_memstream.o libgen/dirname.o unistd/unlink.o string/strstr.o string/strcasecmp.o string/strncasecmp.o stdlib/mkstemp.o string/strtok.o unistd/execvp.o unistd/_exit.o ctype/isalnum.o time/ctime_r.o stdlib/strtold.o sys/time/gettimeofday.o stdio/fgetpos.o stdio/fsetpos.o ctype/isprint.o stdlib/system.o stdio/tmpnam.o unistd/msleep.o stdlib/atof.o stdlib/strtod.o stdio/rename.o sys/stat/mkdir.o unistd/uptime.o
+#OBJ=crt0.o libc.o malloc/malloc.o pty.o sys/mman/mmap.o memset.o assert.o stdio/snprintf.o stdio/vfprintf.o string/memcpy.o string/memcmp.o string/strcmp.o ubsan.o string/strcpy.o isspace.o stdio/puts.o stdio/putchar.o dirent/opendir.o dirent/readdir.o dirent/closedir.o unistd/getopt.o dirent/scandir.o dirent/alphasort.o stdio/printf.o stdio/vdprintf.o stdio/vprintf.o stdio/dprintf.o stdio/vprintf.o string/strlen.o string/strnlen.o stdio/stdin.o stdio/stdout.o stdio/stderr.o stdio/getchar.o stdio/fgetc.o arpa/inet/htons.o arpa/inet/htonl.o stdio/fread.o stdio/fwrite.o stdio/fopen.o stdio/fclose.o stdio/fseek.o ctype/isascii.o stdio/fprintf.o stdlib/atoi.o stdlib/strtol.o ctype/toupper.o ctype/tolower.o string/strcat.o string/strchr.o string/sscanf.o sys/stat/stat.o stdlib/getenv.o string/strrchr.o stdio/ftell.o stdio/tmpfile.o stdio/fgets.o stdio/feof.o stdio/fscanf.o stdio/ungetc.o string/strncmp.o stdio/fputc.o string/strncpy.o stdio/remove.o stdio/ferror.o stdio/fputs.o stdlib/rand.o stdlib/srand.o unistd/getpid.o stdlib/strtoul.o stdio/fflush.o stdlib/abort.o string/strcspn.o time/localtime.o time/time.o time/clock_gettime.o time/gmtime.o time/strftime.o string/strpbrk.o ctype/isdigit.o ctype/isalpha.o ctype/isxdigit.o ctype/ispunct.o stdio/setvbuf.o stdio/fileno.o stdio/putc.o stdio/sprintf.o stdlib/abs.o string/strspn.o stdlib/qsort.o string/memmove.o setjmp/longjmp.o setjmp/setjmp.o
+all: libc.a
+
+%.o: %.c
+ $(CC) $(CFLAGS) -O0 -I. -o $@ -c $< -lgcc
+
+%.o: %.s
+ $(AS) $< -o $@
+
+libc.a: $(OBJ)
+ $(AR) rcs libc.a $(OBJ)
+
+install:
+ cp crt0.o /home/anton/prj/osdev/sysroot/lib/
+ cp libc.a /home/anton/prj/osdev/sysroot/lib/
+ cp -r include /home/anton/prj/osdev/sysroot/usr/
+
+clean:
+ rm libc.a *.o */*.o */*/*.o
diff --git a/userland/libc/arpa/inet.h b/userland/libc/arpa/inet.h
new file mode 100644
index 0000000..7a033f2
--- /dev/null
+++ b/userland/libc/arpa/inet.h
@@ -0,0 +1,4 @@
+#include <stdint.h>
+
+uint32_t htonl(uint32_t hostlong);
+uint16_t htons(uint16_t hostlong);
diff --git a/userland/libc/arpa/inet/htonl.c b/userland/libc/arpa/inet/htonl.c
new file mode 100644
index 0000000..4b66747
--- /dev/null
+++ b/userland/libc/arpa/inet/htonl.c
@@ -0,0 +1,11 @@
+#include <arpa/inet.h>
+#include <endian.h>
+#include <stdint.h>
+
+uint32_t htonl(uint32_t hostlong) {
+#if BYTE_ORDER == LITTLE_ENDIAN
+ hostlong = (uint32_t)(htons(hostlong >> 16)) |
+ (uint32_t)(htons(hostlong & 0xFFFF) << 16);
+#endif
+ return hostlong;
+}
diff --git a/userland/libc/arpa/inet/htons.c b/userland/libc/arpa/inet/htons.c
new file mode 100644
index 0000000..798a64a
--- /dev/null
+++ b/userland/libc/arpa/inet/htons.c
@@ -0,0 +1,10 @@
+#include <arpa/inet.h>
+#include <endian.h>
+#include <stdint.h>
+
+uint16_t htons(uint16_t hostlong) {
+#if BYTE_ORDER == LITTLE_ENDIAN
+ hostlong = ((hostlong & 0xFF00) >> 8) | ((hostlong & 0x00FF) << 8);
+#endif
+ return hostlong;
+}
diff --git a/userland/libc/assert.c b/userland/libc/assert.c
new file mode 100644
index 0000000..4082f64
--- /dev/null
+++ b/userland/libc/assert.c
@@ -0,0 +1,9 @@
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+void aFailed(char *f, int l) {
+ printf("Assert failed\n");
+ printf("%s : %d\n", f, l);
+ exit(1);
+}
diff --git a/userland/libc/assert.h b/userland/libc/assert.h
new file mode 100644
index 0000000..a009e5f
--- /dev/null
+++ b/userland/libc/assert.h
@@ -0,0 +1,10 @@
+#ifndef ASSERT_H
+#define ASSERT_H
+
+#define assert(expr) \
+ { \
+ if (!(expr)) \
+ aFailed(__FILE__, __LINE__); \
+ }
+void aFailed(char *f, int l);
+#endif
diff --git a/userland/libc/crt0.s b/userland/libc/crt0.s
new file mode 100644
index 0000000..05144d4
--- /dev/null
+++ b/userland/libc/crt0.s
@@ -0,0 +1,13 @@
+.global _start
+.extern main
+_start:
+ call main
+ mov %eax, %ebx
+ mov $8, %eax
+ int $0x80
+l:
+ nop
+ nop
+ nop
+ nop
+ jmp l
diff --git a/userland/libc/ctype.h b/userland/libc/ctype.h
new file mode 100644
index 0000000..5be4a89
--- /dev/null
+++ b/userland/libc/ctype.h
@@ -0,0 +1,12 @@
+#ifndef CTYPE_H
+#define CTYPE_H
+
+int isspace(int c);
+int isascii(int c);
+int toupper(int c);
+int tolower(int c);
+int isdigit(int c);
+int isalpha(int c);
+int isxdigit(int c);
+int ispunct(int c);
+#endif
diff --git a/userland/libc/ctype/isalnum.c b/userland/libc/ctype/isalnum.c
new file mode 100644
index 0000000..870728d
--- /dev/null
+++ b/userland/libc/ctype/isalnum.c
@@ -0,0 +1,6 @@
+#include <ctype.h>
+
+// This is probably the most useless libc function I have seen so far.
+int isalnum(int c) {
+ return isalpha(c) || isdigit(c);
+}
diff --git a/userland/libc/ctype/isalpha.c b/userland/libc/ctype/isalpha.c
new file mode 100644
index 0000000..130f493
--- /dev/null
+++ b/userland/libc/ctype/isalpha.c
@@ -0,0 +1,4 @@
+#include <ctype.h>
+
+// https://pubs.opengroup.org/onlinepubs/9699919799/functions/isalpha.html
+int isalpha(int c) { return (('A' <= toupper(c)) && ('Z' >= toupper(c))); }
diff --git a/userland/libc/ctype/isascii.c b/userland/libc/ctype/isascii.c
new file mode 100644
index 0000000..660c8bb
--- /dev/null
+++ b/userland/libc/ctype/isascii.c
@@ -0,0 +1,4 @@
+#include <ctype.h>
+
+// https://pubs.opengroup.org/onlinepubs/9699919799/functions/isascii.html
+int isascii(int c) { return (c < 128); }
diff --git a/userland/libc/ctype/isdigit.c b/userland/libc/ctype/isdigit.c
new file mode 100644
index 0000000..790b9f1
--- /dev/null
+++ b/userland/libc/ctype/isdigit.c
@@ -0,0 +1,6 @@
+#include <ctype.h>
+
+// https://pubs.opengroup.org/onlinepubs/9699919799/functions/isdigit.html
+int isdigit(int c) {
+ return ('0' <= c && c <= '9');
+}
diff --git a/userland/libc/ctype/isprint.c b/userland/libc/ctype/isprint.c
new file mode 100644
index 0000000..e6a3d0e
--- /dev/null
+++ b/userland/libc/ctype/isprint.c
@@ -0,0 +1,3 @@
+#include <ctype.h>
+
+int isprint(int c) { return c > 0x20 && 0x7F != c; }
diff --git a/userland/libc/ctype/ispunct.c b/userland/libc/ctype/ispunct.c
new file mode 100644
index 0000000..18dc7d8
--- /dev/null
+++ b/userland/libc/ctype/ispunct.c
@@ -0,0 +1,6 @@
+#include <ctype.h>
+
+// https://pubs.opengroup.org/onlinepubs/9699919799/functions/ispunct.html
+int ispunct(int c) {
+ return (c == '.');
+}
diff --git a/userland/libc/ctype/isxdigit.c b/userland/libc/ctype/isxdigit.c
new file mode 100644
index 0000000..c843725
--- /dev/null
+++ b/userland/libc/ctype/isxdigit.c
@@ -0,0 +1,6 @@
+#include <ctype.h>
+
+// https://pubs.opengroup.org/onlinepubs/9699919799/functions/isxdigit.html
+int isxdigit(int c) {
+ return isdigit(c) || ('A' >= toupper(c) && 'Z' <= toupper(c));
+}
diff --git a/userland/libc/ctype/tolower.c b/userland/libc/ctype/tolower.c
new file mode 100644
index 0000000..f1bb163
--- /dev/null
+++ b/userland/libc/ctype/tolower.c
@@ -0,0 +1,7 @@
+#include <ctype.h>
+
+int tolower(int c) {
+ if (c >= 'A' && c <= 'Z')
+ return c - 'A' + 'a';
+ return c;
+}
diff --git a/userland/libc/ctype/toupper.c b/userland/libc/ctype/toupper.c
new file mode 100644
index 0000000..0f33886
--- /dev/null
+++ b/userland/libc/ctype/toupper.c
@@ -0,0 +1,7 @@
+#include <ctype.h>
+
+int toupper(int c) {
+ if (c >= 'a' && c <= 'z')
+ return c - 'a' + 'A';
+ return c;
+}
diff --git a/userland/libc/dirent.h b/userland/libc/dirent.h
new file mode 100644
index 0000000..f190a7c
--- /dev/null
+++ b/userland/libc/dirent.h
@@ -0,0 +1,28 @@
+#ifndef DIRENT_H
+#define DIRENT_H
+#include <fcntl.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+struct dirent {
+ ino_t d_ino; // File serial number.
+ char d_name[PATH_MAX]; // Filename string of entry.
+};
+
+typedef struct {
+ int fd;
+ struct dirent internal_direntry;
+ int dir_num;
+} DIR;
+
+DIR *opendir(const char *dirname);
+struct dirent *readdir(DIR *dir);
+int closedir(DIR *dirp);
+int alphasort(const struct dirent **d1, const struct dirent **d2);
+int scandir(const char *dir, struct dirent ***namelist,
+ int (*sel)(const struct dirent *),
+ int (*compar)(const struct dirent **, const struct dirent **));
+#endif
diff --git a/userland/libc/dirent/alphasort.c b/userland/libc/dirent/alphasort.c
new file mode 100644
index 0000000..43a4b5f
--- /dev/null
+++ b/userland/libc/dirent/alphasort.c
@@ -0,0 +1,7 @@
+#include <dirent.h>
+
+int alphasort(const struct dirent **d1, const struct dirent **d2) {
+ // TODO: Actually sort it
+ *d2 = *d1;
+ return 0;
+}
diff --git a/userland/libc/dirent/closedir.c b/userland/libc/dirent/closedir.c
new file mode 100644
index 0000000..e216d7c
--- /dev/null
+++ b/userland/libc/dirent/closedir.c
@@ -0,0 +1,7 @@
+#include <dirent.h>
+
+int closedir(DIR *dir) {
+ close(dir->fd);
+ free(dir);
+ return 0;
+}
diff --git a/userland/libc/dirent/opendir.c b/userland/libc/dirent/opendir.c
new file mode 100644
index 0000000..7bfa562
--- /dev/null
+++ b/userland/libc/dirent/opendir.c
@@ -0,0 +1,11 @@
+#include <dirent.h>
+
+DIR *opendir(const char *dirname) {
+ int fd = open(dirname, O_RDONLY, 0);
+ if (-1 == fd)
+ return NULL;
+ DIR *rc = malloc(sizeof(DIR));
+ rc->fd = fd;
+ rc->dir_num = 0;
+ return rc;
+}
diff --git a/userland/libc/dirent/readdir.c b/userland/libc/dirent/readdir.c
new file mode 100644
index 0000000..88aff48
--- /dev/null
+++ b/userland/libc/dirent/readdir.c
@@ -0,0 +1,14 @@
+#include <dirent.h>
+
+struct dirent *readdir(DIR *dir) {
+ size_t offset = dir->dir_num * sizeof(struct dirent);
+ int rc;
+ if (-1 == (rc = pread(dir->fd, &dir->internal_direntry, sizeof(struct dirent),
+ offset)))
+ return NULL;
+ if (rc < sizeof(struct dirent))
+ return NULL;
+
+ dir->dir_num++;
+ return &(dir->internal_direntry);
+}
diff --git a/userland/libc/dirent/scandir.c b/userland/libc/dirent/scandir.c
new file mode 100644
index 0000000..1520140
--- /dev/null
+++ b/userland/libc/dirent/scandir.c
@@ -0,0 +1,43 @@
+#include <dirent.h>
+#include <stdlib.h>
+#include <string.h>
+
+int nop_sel(const struct dirent *unused) {
+ (void)unused;
+ return 1;
+}
+
+int nop_compar(const struct dirent **d1, const struct dirent **d2) {
+ *d2 = *d1;
+ return 0;
+}
+
+int scandir(const char *dir, struct dirent ***namelist,
+ int (*sel)(const struct dirent *),
+ int (*compar)(const struct dirent **, const struct dirent **)) {
+ if (!sel)
+ sel = nop_sel;
+
+ if (!compar)
+ compar = nop_compar;
+
+ DIR *d = opendir(dir);
+ struct dirent **list = NULL;
+ struct dirent *e;
+ int rc = 0;
+ for (; (e = readdir(d));) {
+ if (!sel(e))
+ continue;
+ struct dirent *p = malloc(sizeof(struct dirent));
+ memcpy(p, e, sizeof(struct dirent));
+ list = realloc(list, (rc + 1) * sizeof(struct dirent *));
+ list[rc] = p;
+ rc++;
+ }
+ // struct dirent **new_list;
+ // compar((const struct dirent **)list, (const struct dirent **)new_list);
+ // *namelist = new_list;
+ *namelist = list;
+ // closedir(d);
+ return rc;
+}
diff --git a/userland/libc/endian.h b/userland/libc/endian.h
new file mode 100644
index 0000000..f265a67
--- /dev/null
+++ b/userland/libc/endian.h
@@ -0,0 +1,2 @@
+#define LITTLE_ENDIAN 0
+#define BYTE_ORDER LITTLE_ENDIAN
diff --git a/userland/libc/errno.h b/userland/libc/errno.h
new file mode 100644
index 0000000..ec9a25e
--- /dev/null
+++ b/userland/libc/errno.h
@@ -0,0 +1,87 @@
+#ifndef ERRNO_H
+#define ERRNO_H
+// https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/errno.h.html
+#define E2BIG 1 // Argument list too long.
+#define EACCES 2 // Permission denied.
+#define EADDRINUSE 3 // Address in use.
+#define EADDRNOTAVAIL 4 // Address not available.
+#define EAFNOSUPPORT 5 // Address family not supported.
+#define EAGAIN 6 // Resource unavailable, try again.
+#define EALREADY 7 // Connection already in progress.
+#define EBADF 8 // Bad file descriptor.
+#define EBADMSG 9 // Bad message.
+#define EBUSY 10 // Device or resource busy.
+#define ECANCELED 11 // Operation canceled.
+#define ECHILD 12 // No child processes.
+#define ECONNABORTED 13 // Connection aborted.
+#define ECONNREFUSED 14 // Connection refused.
+#define ECONNRESET 15 // Connection reset.
+#define EDEADLK 16 // Resource deadlock would occur.
+#define EDESTADDRREQ 17 // Destination address required.
+#define EDOM 18 // Mathematics argument out of domain of function.
+#define EDQUOT 19 // Reserved.
+#define EEXIST 20 // File exists.
+#define EFAULT 21 // Bad address.
+#define EFBIG 22 // File too large.
+#define EHOSTUNREACH 23 // Host is unreachable.
+#define EIDRM 24 // Identifier removed.
+#define EILSEQ 25 // Illegal byte sequence.
+#define EINPROGRESS 26 // Operation in progress.
+#define EINTR 27 // Interrupted function.
+#define EINVAL 28 // Invalid argument.
+#define EIO 29 // I/O error.
+#define EISCONN 30 // Socket is connected.
+#define EISDIR 31 // Is a directory.
+#define ELOOP 32 // Too many levels of symbolic links.
+#define EMFILE 33 // File descriptor value too large.
+#define EMLINK 34 // Too many links.
+#define EMSGSIZE 35 // Message too large.
+#define EMULTIHOP 36 // Reserved.
+#define ENAMETOOLONG 37 // Filename too long.
+#define ENETDOWN 38 // Network is down.
+#define ENETRESET 39 // Connection aborted by network.
+#define ENETUNREACH 40 // Network unreachable.
+#define ENFILE 41 // Too many files open in system.
+#define ENOBUFS 42 // No buffer space available.
+#define ENODATA 43 // No message is available on the STREAM head read queue.
+#define ENODEV 44 // No such device.
+#define ENOENT 45 // No such file or directory.
+#define ENOEXEC 46 // Executable file format error.
+#define ENOLCK 47 // No locks available.
+#define ENOLINK 48 // Reserved.
+#define ENOMEM 49 // Not enough space.
+#define ENOMSG 50 // No message of the desired type.
+#define ENOPROTOOPT 51 // Protocol not available.
+#define ENOSPC 52 // No space left on device.
+#define ENOSR 53 // No STREAM resources.
+#define ENOSTR 54 // Not a STREAM.
+#define ENOSYS 55 // Functionality not supported.
+#define ENOTCONN 56 // The socket is not connected.
+#define ENOTDIR 57 // Not a directory or a symbolic link to a directory.
+#define ENOTEMPTY 58 // Directory not empty.
+#define ENOTRECOVERABLE 59 // State not recoverable.
+#define ENOTSOCK 60 // Not a socket.
+#define ENOTSUP 61 // Not supported (may be the same value as.
+#define ENOTTY 62 // Inappropriate I/O control operation.
+#define ENXIO 63 // No such device or address.
+#define EOPNOTSUPP ENOTSUP // Operation not supported on socket.
+#define EOVERFLOW 65 // Value too large to be stored in data type.
+#define EOWNERDEAD 66 // Previous owner died.
+#define EPERM 67 // Operation not permitted.
+#define EPIPE 68 // Broken pipe.
+#define EPROTO 69 // Protocol error.
+#define EPROTONOSUPPORT 70 // Protocol not supported.
+#define EPROTOTYPE 71 // Protocol wrong type for socket.
+#define ERANGE 72 // Result too large.
+#define EROFS 73 // Read-only file system.
+#define ESPIPE 74 // Invalid seek.
+#define ESRCH 75 // No such process.
+#define ESTALE 76 // Reserved.
+#define ETIME 77 // Stream ioctl() timeout.
+#define ETIMEDOUT 78 // Connection timed out.
+#define ETXTBSY 79 // Text file busy.
+#define EWOULDBLOCK EAGAIN // Operation would block.
+#define EXDEV 81 // Cross-device link.
+
+extern int errno;
+#endif
diff --git a/userland/libc/fcntl.h b/userland/libc/fcntl.h
new file mode 100644
index 0000000..4c1eb9c
--- /dev/null
+++ b/userland/libc/fcntl.h
@@ -0,0 +1,10 @@
+// FIXME: Is there some standard value for this?
+#define O_NONBLOCK (1 << 0)
+#define O_READ (1 << 1)
+#define O_WRITE (1 << 2)
+#define O_CREAT (1 << 3)
+#define O_RDONLY O_READ
+#define O_WRONLY O_WRITE
+#define O_RDWR (O_WRITE | O_READ)
+
+int open(const char *file, int flags, int mode);
diff --git a/userland/libc/include/arpa/inet.h b/userland/libc/include/arpa/inet.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/userland/libc/include/arpa/inet.h
diff --git a/userland/libc/include/assert.h b/userland/libc/include/assert.h
new file mode 100644
index 0000000..a009e5f
--- /dev/null
+++ b/userland/libc/include/assert.h
@@ -0,0 +1,10 @@
+#ifndef ASSERT_H
+#define ASSERT_H
+
+#define assert(expr) \
+ { \
+ if (!(expr)) \
+ aFailed(__FILE__, __LINE__); \
+ }
+void aFailed(char *f, int l);
+#endif
diff --git a/userland/libc/include/byteswap.h b/userland/libc/include/byteswap.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/userland/libc/include/byteswap.h
diff --git a/userland/libc/include/ctype.h b/userland/libc/include/ctype.h
new file mode 100644
index 0000000..7c8c311
--- /dev/null
+++ b/userland/libc/include/ctype.h
@@ -0,0 +1,14 @@
+#ifndef CTYPE_H
+#define CTYPE_H
+
+int isspace(int c);
+int isascii(int c);
+int toupper(int c);
+int tolower(int c);
+int isdigit(int c);
+int isalpha(int c);
+int isxdigit(int c);
+int ispunct(int c);
+int isalnum(int c);
+int isprint(int c);
+#endif
diff --git a/userland/libc/include/dirent.h b/userland/libc/include/dirent.h
new file mode 100644
index 0000000..f190a7c
--- /dev/null
+++ b/userland/libc/include/dirent.h
@@ -0,0 +1,28 @@
+#ifndef DIRENT_H
+#define DIRENT_H
+#include <fcntl.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+struct dirent {
+ ino_t d_ino; // File serial number.
+ char d_name[PATH_MAX]; // Filename string of entry.
+};
+
+typedef struct {
+ int fd;
+ struct dirent internal_direntry;
+ int dir_num;
+} DIR;
+
+DIR *opendir(const char *dirname);
+struct dirent *readdir(DIR *dir);
+int closedir(DIR *dirp);
+int alphasort(const struct dirent **d1, const struct dirent **d2);
+int scandir(const char *dir, struct dirent ***namelist,
+ int (*sel)(const struct dirent *),
+ int (*compar)(const struct dirent **, const struct dirent **));
+#endif
diff --git a/userland/libc/include/endian.h b/userland/libc/include/endian.h
new file mode 100644
index 0000000..f265a67
--- /dev/null
+++ b/userland/libc/include/endian.h
@@ -0,0 +1,2 @@
+#define LITTLE_ENDIAN 0
+#define BYTE_ORDER LITTLE_ENDIAN
diff --git a/userland/libc/include/err.h b/userland/libc/include/err.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/userland/libc/include/err.h
diff --git a/userland/libc/include/errno.h b/userland/libc/include/errno.h
new file mode 100644
index 0000000..ec9a25e
--- /dev/null
+++ b/userland/libc/include/errno.h
@@ -0,0 +1,87 @@
+#ifndef ERRNO_H
+#define ERRNO_H
+// https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/errno.h.html
+#define E2BIG 1 // Argument list too long.
+#define EACCES 2 // Permission denied.
+#define EADDRINUSE 3 // Address in use.
+#define EADDRNOTAVAIL 4 // Address not available.
+#define EAFNOSUPPORT 5 // Address family not supported.
+#define EAGAIN 6 // Resource unavailable, try again.
+#define EALREADY 7 // Connection already in progress.
+#define EBADF 8 // Bad file descriptor.
+#define EBADMSG 9 // Bad message.
+#define EBUSY 10 // Device or resource busy.
+#define ECANCELED 11 // Operation canceled.
+#define ECHILD 12 // No child processes.
+#define ECONNABORTED 13 // Connection aborted.
+#define ECONNREFUSED 14 // Connection refused.
+#define ECONNRESET 15 // Connection reset.
+#define EDEADLK 16 // Resource deadlock would occur.
+#define EDESTADDRREQ 17 // Destination address required.
+#define EDOM 18 // Mathematics argument out of domain of function.
+#define EDQUOT 19 // Reserved.
+#define EEXIST 20 // File exists.
+#define EFAULT 21 // Bad address.
+#define EFBIG 22 // File too large.
+#define EHOSTUNREACH 23 // Host is unreachable.
+#define EIDRM 24 // Identifier removed.
+#define EILSEQ 25 // Illegal byte sequence.
+#define EINPROGRESS 26 // Operation in progress.
+#define EINTR 27 // Interrupted function.
+#define EINVAL 28 // Invalid argument.
+#define EIO 29 // I/O error.
+#define EISCONN 30 // Socket is connected.
+#define EISDIR 31 // Is a directory.
+#define ELOOP 32 // Too many levels of symbolic links.
+#define EMFILE 33 // File descriptor value too large.
+#define EMLINK 34 // Too many links.
+#define EMSGSIZE 35 // Message too large.
+#define EMULTIHOP 36 // Reserved.
+#define ENAMETOOLONG 37 // Filename too long.
+#define ENETDOWN 38 // Network is down.
+#define ENETRESET 39 // Connection aborted by network.
+#define ENETUNREACH 40 // Network unreachable.
+#define ENFILE 41 // Too many files open in system.
+#define ENOBUFS 42 // No buffer space available.
+#define ENODATA 43 // No message is available on the STREAM head read queue.
+#define ENODEV 44 // No such device.
+#define ENOENT 45 // No such file or directory.
+#define ENOEXEC 46 // Executable file format error.
+#define ENOLCK 47 // No locks available.
+#define ENOLINK 48 // Reserved.
+#define ENOMEM 49 // Not enough space.
+#define ENOMSG 50 // No message of the desired type.
+#define ENOPROTOOPT 51 // Protocol not available.
+#define ENOSPC 52 // No space left on device.
+#define ENOSR 53 // No STREAM resources.
+#define ENOSTR 54 // Not a STREAM.
+#define ENOSYS 55 // Functionality not supported.
+#define ENOTCONN 56 // The socket is not connected.
+#define ENOTDIR 57 // Not a directory or a symbolic link to a directory.
+#define ENOTEMPTY 58 // Directory not empty.
+#define ENOTRECOVERABLE 59 // State not recoverable.
+#define ENOTSOCK 60 // Not a socket.
+#define ENOTSUP 61 // Not supported (may be the same value as.
+#define ENOTTY 62 // Inappropriate I/O control operation.
+#define ENXIO 63 // No such device or address.
+#define EOPNOTSUPP ENOTSUP // Operation not supported on socket.
+#define EOVERFLOW 65 // Value too large to be stored in data type.
+#define EOWNERDEAD 66 // Previous owner died.
+#define EPERM 67 // Operation not permitted.
+#define EPIPE 68 // Broken pipe.
+#define EPROTO 69 // Protocol error.
+#define EPROTONOSUPPORT 70 // Protocol not supported.
+#define EPROTOTYPE 71 // Protocol wrong type for socket.
+#define ERANGE 72 // Result too large.
+#define EROFS 73 // Read-only file system.
+#define ESPIPE 74 // Invalid seek.
+#define ESRCH 75 // No such process.
+#define ESTALE 76 // Reserved.
+#define ETIME 77 // Stream ioctl() timeout.
+#define ETIMEDOUT 78 // Connection timed out.
+#define ETXTBSY 79 // Text file busy.
+#define EWOULDBLOCK EAGAIN // Operation would block.
+#define EXDEV 81 // Cross-device link.
+
+extern int errno;
+#endif
diff --git a/userland/libc/include/fcntl.h b/userland/libc/include/fcntl.h
new file mode 100644
index 0000000..7f0906d
--- /dev/null
+++ b/userland/libc/include/fcntl.h
@@ -0,0 +1,12 @@
+// FIXME: Is there some standard value for this?
+#define O_NONBLOCK (1 << 0)
+#define O_READ (1 << 1)
+#define O_WRITE (1 << 2)
+#define O_CREAT (1 << 3)
+#define O_TRUNC (1 << 4)
+
+#define O_RDONLY O_READ
+#define O_WRONLY O_WRITE
+#define O_RDWR (O_WRITE | O_READ)
+
+int open(const char *file, int flags, int mode);
diff --git a/userland/libc/include/fnmatch.h b/userland/libc/include/fnmatch.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/userland/libc/include/fnmatch.h
diff --git a/userland/libc/include/glob.h b/userland/libc/include/glob.h
new file mode 100644
index 0000000..f9e9c57
--- /dev/null
+++ b/userland/libc/include/glob.h
@@ -0,0 +1,10 @@
+#ifndef GLOB_H
+#define GLOB_H
+#include <stddef.h>
+
+typedef struct {
+ size_t gl_pathc; // Count of paths matched by pattern.
+ char **gl_pathv; // Pointer to a list of matched pathnames
+ size_t gl_offs; // Slots to reserve at the beginning of gl_pathv.
+} glob_t;
+#endif
diff --git a/userland/libc/include/grp.h b/userland/libc/include/grp.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/userland/libc/include/grp.h
diff --git a/userland/libc/include/input.h b/userland/libc/include/input.h
new file mode 100644
index 0000000..a6602f5
--- /dev/null
+++ b/userland/libc/include/input.h
@@ -0,0 +1,9 @@
+#ifndef INPUT_H
+#define INPUT_H
+#include <stdint.h>
+
+struct input_event {
+ uint16_t key;
+ uint8_t status;
+};
+#endif
diff --git a/userland/libc/include/inttypes.h b/userland/libc/include/inttypes.h
new file mode 100644
index 0000000..adde7c8
--- /dev/null
+++ b/userland/libc/include/inttypes.h
@@ -0,0 +1,19 @@
+#include <stdint.h>
+
+// FIXME: These are not correct
+#define PRId8 "d"
+#define PRId16 "d"
+#define PRId32 "d"
+#define PRId64 "d"
+#define PRIu8 "d"
+#define PRIu16 "d"
+#define PRIu32 "d"
+#define PRIu64 "d"
+#define PRIx8 "x"
+#define PRIx16 "x"
+#define PRIx32 "x"
+#define PRIx64 "x"
+#define PRIX8 "x"
+#define PRIX16 "x"
+#define PRIX32 "x"
+#define PRIX64 "x"
diff --git a/userland/libc/include/langinfo.h b/userland/libc/include/langinfo.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/userland/libc/include/langinfo.h
diff --git a/userland/libc/include/libgen.h b/userland/libc/include/libgen.h
new file mode 100644
index 0000000..16dc3ed
--- /dev/null
+++ b/userland/libc/include/libgen.h
@@ -0,0 +1,6 @@
+#ifndef LIBGEN_H
+#define LIBGEN_H
+
+char *basename(char *path);
+char *dirname(char *path);
+#endif
diff --git a/userland/libc/include/limits.h b/userland/libc/include/limits.h
new file mode 100644
index 0000000..6d0abe0
--- /dev/null
+++ b/userland/libc/include/limits.h
@@ -0,0 +1,4 @@
+#define PATH_MAX 256
+#define FILENAME_MAX PATH_MAX
+#define ULONG_MAX 0xFFFFFFFFUL
+#define LONG_MAX 2147483647
diff --git a/userland/libc/include/locale.h b/userland/libc/include/locale.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/userland/libc/include/locale.h
diff --git a/userland/libc/include/math.h b/userland/libc/include/math.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/userland/libc/include/math.h
diff --git a/userland/libc/include/net/if.h b/userland/libc/include/net/if.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/userland/libc/include/net/if.h
diff --git a/userland/libc/include/netdb.h b/userland/libc/include/netdb.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/userland/libc/include/netdb.h
diff --git a/userland/libc/include/netinet/in.h b/userland/libc/include/netinet/in.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/userland/libc/include/netinet/in.h
diff --git a/userland/libc/include/netinet/tcp.h b/userland/libc/include/netinet/tcp.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/userland/libc/include/netinet/tcp.h
diff --git a/userland/libc/include/paths.h b/userland/libc/include/paths.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/userland/libc/include/paths.h
diff --git a/userland/libc/include/poll.h b/userland/libc/include/poll.h
new file mode 100644
index 0000000..e3c6d8d
--- /dev/null
+++ b/userland/libc/include/poll.h
@@ -0,0 +1,17 @@
+#ifndef POLL_H
+#define POLL_H
+#include <stddef.h>
+
+#define POLLIN (1 << 0)
+#define POLLPRI (1 << 1)
+#define POLLOUT (1 << 2)
+#define POLLHUP (1 << 3)
+
+struct pollfd {
+ int fd;
+ short events;
+ short revents;
+};
+
+int poll(struct pollfd *fds, size_t nfds, int timeout);
+#endif
diff --git a/userland/libc/include/pty.h b/userland/libc/include/pty.h
new file mode 100644
index 0000000..b8ce978
--- /dev/null
+++ b/userland/libc/include/pty.h
@@ -0,0 +1,6 @@
+#ifndef PTY_H
+#define PTY_H
+int openpty(int *amaster, int *aslave, char *name,
+ /*const struct termios*/ void *termp,
+ /*const struct winsize*/ void *winp);
+#endif
diff --git a/userland/libc/include/pwd.h b/userland/libc/include/pwd.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/userland/libc/include/pwd.h
diff --git a/userland/libc/include/regex.h b/userland/libc/include/regex.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/userland/libc/include/regex.h
diff --git a/userland/libc/include/sched.h b/userland/libc/include/sched.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/userland/libc/include/sched.h
diff --git a/userland/libc/include/setjmp.h b/userland/libc/include/setjmp.h
new file mode 100644
index 0000000..ea15cf3
--- /dev/null
+++ b/userland/libc/include/setjmp.h
@@ -0,0 +1,14 @@
+#ifndef SETJMP_H
+#define SETJMP_H
+typedef unsigned long __jmp_buf[6];
+typedef struct __jmp_buf_tag {
+ __jmp_buf __jb;
+ unsigned long __fl;
+ unsigned long __ss[128/sizeof(long)];
+} jmp_buf[1];
+typedef jmp_buf sigjmp_buf;
+
+void _longjmp(jmp_buf, int);
+void longjmp(jmp_buf, int);
+void siglongjmp(sigjmp_buf, int);
+#endif
diff --git a/userland/libc/include/signal.h b/userland/libc/include/signal.h
new file mode 100644
index 0000000..2e6566d
--- /dev/null
+++ b/userland/libc/include/signal.h
@@ -0,0 +1,9 @@
+#ifndef SIGNAL_H
+#define SIGNAL_H
+#define SIGHUP 0
+#define SIGINT 1
+#define SIGWINCH 2
+#define SIGQUIT 3
+#define SIG_IGN 4
+typedef int sig_atomic_t;
+#endif // SIGNAL_H
diff --git a/userland/libc/include/socket.h b/userland/libc/include/socket.h
new file mode 100644
index 0000000..5e86b45
--- /dev/null
+++ b/userland/libc/include/socket.h
@@ -0,0 +1,41 @@
+#include <stddef.h>
+#include <stdint.h>
+
+#define AF_UNIX 0
+#define AF_LOCAL AF_UNIX
+
+#define INADDR_ANY 0
+
+typedef struct {
+ int domain;
+ int type;
+ int protocol;
+
+ // UNIX socket
+ char *path;
+ int incoming_fd;
+} SOCKET;
+
+typedef struct {
+ char *path;
+ SOCKET *s;
+} OPEN_UNIX_SOCKET;
+
+typedef uint32_t in_addr_t;
+typedef uint16_t in_port_t;
+typedef unsigned int sa_family_t;
+typedef uint32_t socklen_t;
+
+struct sockaddr {
+ sa_family_t sa_family; /* Address family */
+ char *sa_data; /* Socket address */
+};
+
+struct sockaddr_un {
+ sa_family_t sun_family; /* Address family */
+ char *sun_path; /* Socket pathname */
+};
+
+int socket(int domain, int type, int protocol);
+int accept(int socket, struct sockaddr *address, socklen_t *address_len);
+int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
diff --git a/userland/libc/include/stdio.h b/userland/libc/include/stdio.h
new file mode 100644
index 0000000..014e2ac
--- /dev/null
+++ b/userland/libc/include/stdio.h
@@ -0,0 +1,116 @@
+#ifndef STDIO_H
+#define STDIO_H
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdint.h>
+
+// FIXME: Most of these should probably not be here. But I am too lazy
+// to fix it right now. This is futures mees problem to deal wth.
+
+#define EOF (-1)
+
+#define SEEK_SET 0
+#define SEEK_CUR 1
+#define SEEK_END 2
+
+#define BUFSIZ 4096
+
+// https://pubs.opengroup.org/onlinepubs/9699919799/functions/setvbuf.html
+#define _IOFBF 1 // shall cause input/output to be fully buffered.
+#define _IOLBF 2 // shall cause input/output to be line buffered.
+#define _IONBF 3 // shall cause input/output to be unbuffered.
+
+typedef long fpos_t;
+
+typedef struct __IO_FILE FILE;
+struct __IO_FILE {
+ size_t (*write)(FILE *, const unsigned char *, size_t);
+ size_t (*read)(FILE *, unsigned char *, size_t);
+ int (*seek)(FILE *, long, int);
+ long offset_in_file;
+ int buffered_char;
+ int has_buffered_char;
+ int fd;
+ uint8_t is_eof;
+ uint8_t has_error;
+ uint64_t file_size;
+ void *cookie;
+};
+
+size_t write_fd(FILE *f, const unsigned char *s, size_t l);
+size_t read_fd(FILE *f, unsigned char *s, size_t l);
+int seek_fd(FILE *stream, long offset, int whence);
+
+typedef struct {
+ int fd;
+} FILE_FD_COOKIE;
+
+extern FILE __stdin_FILE;
+extern FILE __stdout_FILE;
+extern FILE __stderr_FILE;
+
+#define stdin (&__stdin_FILE)
+#define stdout (&__stdout_FILE)
+//#define stderr (&__stderr_FILE)
+#define stderr (&__stdout_FILE)
+
+typedef int mode_t;
+
+void perror(const char *s);
+
+int putchar(int c);
+int puts(const char *s);
+int brk(void *addr);
+void *sbrk(intptr_t increment);
+int write(int fd, const char *buf, size_t count);
+int pwrite(int fd, const char *buf, size_t count, size_t offset);
+int printf(const char *format, ...);
+int pread(int fd, void *buf, size_t count, size_t offset);
+int read(int fd, void *buf, size_t count);
+int fork(void);
+int memcmp(const void *s1, const void *s2, size_t n);
+int wait(int *stat_loc);
+void exit(int status);
+void *memcpy(void *dest, const void *src, uint32_t n);
+int shm_open(const char *name, int oflag, mode_t mode);
+int dprintf(int fd, const char *format, ...);
+int vdprintf(int fd, const char *format, va_list ap);
+int vprintf(const char *format, va_list ap);
+int snprintf(char *str, size_t size, const char *format, ...);
+int vsnprintf(char *str, size_t size, const char *format, va_list ap);
+int vfprintf(FILE *f, const char *fmt, va_list ap);
+int fgetc(FILE *stream);
+int getchar(void);
+#define getc(_a) fgetc(_a)
+size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
+size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
+FILE *fopen(const char *pathname, const char *mode);
+int fclose(FILE *stream);
+int fseek(FILE *stream, long offset, int whence);
+int fprintf(FILE *f, const char *fmt, ...);
+int atoi(const char *str);
+long strtol(const char *nptr, char **endptr, int base);
+char *strchr(const char *s, int c);
+char *strcat(char *s1, const char *s2);
+char *fgets(char *s, int n, FILE *stream);
+FILE *tmpfile(void);
+int feof(FILE *stream);
+int fscanf(FILE *stream, const char *format, ...);
+int ungetc(int c, FILE *stream);
+long ftell(FILE *stream);
+int fputc(int c, FILE *stream);
+int remove(const char *path);
+int ferror(FILE *stream);
+int fputs(const char *s, FILE *stream);
+int fflush(FILE *stream);
+int setvbuf(FILE *stream, char *restrict buf, int type, size_t size);
+int fileno(FILE *stream);
+int putc(int c, FILE *stream);
+int vsprintf(char *str, const char *format, va_list ap);
+int sprintf(char *str, const char *format, ...);
+FILE *open_memstream(char **bufp, size_t *sizep);
+int fsetpos(FILE *stream, const fpos_t *pos);
+int fgetpos(FILE *restrict stream, fpos_t *restrict pos);
+char *tmpnam(char *s);
+int rename(const char *old, const char *new);
+#endif
diff --git a/userland/libc/include/stdlib.h b/userland/libc/include/stdlib.h
new file mode 100644
index 0000000..c88f2f3
--- /dev/null
+++ b/userland/libc/include/stdlib.h
@@ -0,0 +1,32 @@
+#ifndef STDLIB_H
+#define STDLIB_H
+#include <limits.h>
+#include <stddef.h>
+#define RAND_MAX (UINT32_MAX)
+#define EXIT_SUCCESS 0
+#define EXIT_FAILURE 1
+
+typedef size_t size_t; // only for 32 bit
+
+void *malloc(size_t s);
+void *calloc(size_t nelem, size_t elsize);
+void *realloc(void *ptr, size_t size);
+void free(void *p);
+char *getenv(const char *name);
+int rand(void);
+void srand(unsigned int seed);
+unsigned long strtoul(const char *restrict str, char **restrict endptr,
+ int base);
+long strtol(const char *str, char **restrict endptr, int base);
+void abort(void);
+int abs(int i);
+void qsort(void *base, size_t nel, size_t width,
+ int (*compar)(const void *, const void *));
+int atexit(void (*func)(void));
+int mkstemp(char *template);
+long double strtold(const char *restrict nptr, char **restrict endptr);
+int system(const char *command);
+double atof(const char *str);
+double strtod(const char *restrict nptr, char **restrict endptr);
+int atoi(const char *str);
+#endif
diff --git a/userland/libc/include/string.h b/userland/libc/include/string.h
new file mode 100644
index 0000000..0c61efa
--- /dev/null
+++ b/userland/libc/include/string.h
@@ -0,0 +1,29 @@
+#ifndef STRING_H
+#define STRING_H
+#include <stddef.h>
+#include <stdint.h>
+
+char *strerror(int errnum);
+void *memset(void *s, int c, size_t n);
+void *memcpy(void *dest, const void *src, uint32_t n);
+int strcmp(const char *s1, const char *s2);
+char *strcpy(char *dest, const char *src);
+size_t strlen(const char *s);
+size_t strnlen(const char *s, size_t maxlen);
+int sscanf(const char *s, const char *restrict format, ...);
+char *strrchr(const char *s, int c);
+int strncmp(const char *s1, const char *s2, size_t n);
+char *strncpy(char *s1, const char *s2, size_t n);
+size_t *strlcpy(char *s1, const char *s2, size_t n);
+size_t strcspn(const char *s1, const char *s2);
+char *strpbrk(const char *s1, const char *s2);
+size_t strspn(const char *s1, const char *s2);
+void *memmove(void *s1, const void *s2, size_t n);
+char *strdup(const char *s);
+char *strndup(const char *s, size_t size);
+char *strstr(const char *s1, const char *s2);
+int strncasecmp(const char *s1, const char *s2, size_t n);
+int strcasecmp(const char *s1, const char *s2);
+char *strtok(char *restrict s, const char *restrict sep);
+char *strcat(char *restrict s1, const char *restrict s2);
+#endif
diff --git a/userland/libc/include/strings.h b/userland/libc/include/strings.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/userland/libc/include/strings.h
diff --git a/userland/libc/include/sys/ioctl.h b/userland/libc/include/sys/ioctl.h
new file mode 100644
index 0000000..a373a4b
--- /dev/null
+++ b/userland/libc/include/sys/ioctl.h
@@ -0,0 +1,10 @@
+#ifndef IOCTL_H
+#define IOCTL_H
+#define TIOCGWINSZ 0
+struct winsize {
+ unsigned short ws_row;
+ unsigned short ws_col;
+ unsigned short ws_xpixel;
+ unsigned short ws_ypixel;
+};
+#endif // IOCTL_H
diff --git a/userland/libc/include/sys/mman.h b/userland/libc/include/sys/mman.h
new file mode 100644
index 0000000..7dfe29a
--- /dev/null
+++ b/userland/libc/include/sys/mman.h
@@ -0,0 +1,15 @@
+#ifndef MMAP_H
+#define MMAP_H
+#include <stdint.h>
+#include <stddef.h>
+
+#define PROT_READ (1 << 0)
+#define PROT_WRITE (1 << 1)
+
+#define MAP_PRIVATE (1 << 0)
+#define MAP_ANONYMOUS (1<< 1)
+#define MAP_SHARED (1<< 2)
+
+void *mmap(void *addr, size_t length, int prot, int flags, int fd,
+ size_t offset);
+#endif
diff --git a/userland/libc/include/sys/mount.h b/userland/libc/include/sys/mount.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/userland/libc/include/sys/mount.h
diff --git a/userland/libc/include/sys/resource.h b/userland/libc/include/sys/resource.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/userland/libc/include/sys/resource.h
diff --git a/userland/libc/include/sys/socket.h b/userland/libc/include/sys/socket.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/userland/libc/include/sys/socket.h
diff --git a/userland/libc/include/sys/stat.h b/userland/libc/include/sys/stat.h
new file mode 100644
index 0000000..178d014
--- /dev/null
+++ b/userland/libc/include/sys/stat.h
@@ -0,0 +1,31 @@
+#ifndef STAT_H
+#define STAT_H
+#include <sys/types.h>
+#include <time.h>
+
+struct stat {
+ dev_t st_dev; // Device ID of device containing file.
+ ino_t st_ino; // File serial number.
+ mode_t st_mode; // Mode of file (see below).
+ nlink_t st_nlink; // Number of hard links to the file.
+ uid_t st_uid; // User ID of file.
+ gid_t st_gid; // Group ID of file.
+ dev_t st_rdev; // Device ID (if file is character or block special).
+ off_t st_size; // For regular files, the file size in bytes.
+ // For symbolic links, the length in bytes of the
+ // pathname contained in the symbolic link.
+ // For a shared memory object, the length in bytes.
+ // For a typed memory object, the length in bytes.
+ // For other file types, the use of this field is
+ // unspecified.
+ struct timespec st_atime; // Last data access timestamp.
+ struct timespec st_mtime; // Last data modification timestamp.
+ struct timespec st_ctime; // Last file status change timestamp.
+ blksize_t st_blksize; // A file system-specific preferred I/O block size
+ // for this object. In some file system types, this
+ // may vary from file to file.
+ blkcnt_t st_blocks; // Number of blocks allocated for this object.
+};
+int stat(const char *path, struct stat *buf);
+int mkdir(const char *path, mode_t mode);
+#endif
diff --git a/userland/libc/include/sys/statvfs.h b/userland/libc/include/sys/statvfs.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/userland/libc/include/sys/statvfs.h
diff --git a/userland/libc/include/sys/syscall.h b/userland/libc/include/sys/syscall.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/userland/libc/include/sys/syscall.h
diff --git a/userland/libc/include/sys/time.h b/userland/libc/include/sys/time.h
new file mode 100644
index 0000000..a675d9e
--- /dev/null
+++ b/userland/libc/include/sys/time.h
@@ -0,0 +1,41 @@
+#ifndef TIME_H
+#define TIME_H
+#include <stddef.h>
+#include <sys/types.h>
+#include <time.h>
+
+#define CLOCK_REALTIME 0
+
+struct tm {
+ int tm_sec;
+ int tm_min;
+ int tm_hour;
+ int tm_mday;
+ int tm_mon;
+ int tm_year;
+ int tm_wday;
+ int tm_yday;
+ int tm_isdst;
+ long __tm_gmtoff;
+ const char *__tm_zone;
+};
+
+typedef int clockid_t;
+struct timespec {
+ time_t tv_sec; // Seconds.
+ long tv_nsec; // Nanoseconds.
+};
+
+struct timeval {
+ time_t tv_sec;
+ suseconds_t tv_usec;
+};
+
+time_t time(time_t *tloc);
+int clock_gettime(clockid_t clock_id, struct timespec *tp);
+struct tm *localtime(const time_t *timer);
+struct tm *gmtime(const time_t *timer);
+size_t strftime(char *restrict s, size_t maxsize, const char *restrict format,
+ const struct tm *restrict timeptr);
+int gettimeofday(struct timeval *tp, void *tzp);
+#endif
diff --git a/userland/libc/include/sys/times.h b/userland/libc/include/sys/times.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/userland/libc/include/sys/times.h
diff --git a/userland/libc/include/sys/types.h b/userland/libc/include/sys/types.h
new file mode 100644
index 0000000..48c57f9
--- /dev/null
+++ b/userland/libc/include/sys/types.h
@@ -0,0 +1,28 @@
+#ifndef TYPES_H
+#define TYPES_H
+typedef unsigned int ino_t;
+
+typedef int mode_t;
+
+typedef int nlink_t;
+typedef int uid_t;
+typedef int gid_t;
+typedef int id_t;
+
+typedef int blkcnt_t;
+typedef int off_t;
+
+typedef int dev_t;
+typedef unsigned int fsblkcnt_t;
+typedef unsigned int fsfilcnt_t;
+typedef unsigned int ino_t;
+//typedef unsigned int size_t;
+
+typedef int blksize_t;
+typedef int pid_t;
+typedef int ssize_t;
+
+//typedef int clock_t;
+typedef int time_t;
+typedef unsigned int suseconds_t;
+#endif
diff --git a/userland/libc/include/sys/ucontext.h b/userland/libc/include/sys/ucontext.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/userland/libc/include/sys/ucontext.h
diff --git a/userland/libc/include/sys/un.h b/userland/libc/include/sys/un.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/userland/libc/include/sys/un.h
diff --git a/userland/libc/include/sys/utsname.h b/userland/libc/include/sys/utsname.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/userland/libc/include/sys/utsname.h
diff --git a/userland/libc/include/sys/wait.h b/userland/libc/include/sys/wait.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/userland/libc/include/sys/wait.h
diff --git a/userland/libc/include/syscall.h b/userland/libc/include/syscall.h
new file mode 100644
index 0000000..caa7779
--- /dev/null
+++ b/userland/libc/include/syscall.h
@@ -0,0 +1,150 @@
+#ifndef SYSCALL_H
+#define SYSCALL_H
+#include "socket.h"
+#include <stddef.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+#define SYS_OPEN 0
+#define SYS_READ 1
+#define SYS_WRITE 2
+#define SYS_PREAD 3
+#define SYS_PWRITE 4
+#define SYS_FORK 5
+#define SYS_EXEC 6
+#define SYS_GETPID 7
+#define SYS_EXIT 8
+#define SYS_WAIT 9
+#define SYS_BRK 10
+#define SYS_SBRK 11
+#define SYS_PIPE 12
+#define SYS_DUP2 13
+#define SYS_CLOSE 14
+#define SYS_OPENPTY 15
+#define SYS_POLL 16
+#define SYS_MMAP 17
+#define SYS_ACCEPT 18
+#define SYS_BIND 19
+#define SYS_SOCKET 20
+#define SYS_SHM_OPEN 21
+#define SYS_FTRUNCATE 22
+#define SYS_STAT 23
+#define SYS_MSLEEP 24
+#define SYS_UPTIME 25
+
+int syscall(uint32_t eax, uint32_t ebx, uint32_t ecx, uint32_t edx,
+ uint32_t esi, uint32_t edi);
+int s_syscall(int sys);
+
+extern int errno;
+#define RC_ERRNO(_rc) \
+ { \
+ int c = _rc; \
+ if (c < 0) { \
+ errno = -(c); \
+ return -1; \
+ } \
+ return c; \
+ }
+
+typedef int mode_t;
+
+typedef struct SYS_OPEN_PARAMS {
+ const char *file;
+ int flags;
+ int mode;
+} __attribute__((packed)) SYS_OPEN_PARAMS;
+
+typedef struct SYS_PREAD_PARAMS {
+ int fd;
+ void *buf;
+ size_t count;
+ size_t offset;
+} __attribute__((packed)) SYS_PREAD_PARAMS;
+
+typedef struct SYS_READ_PARAMS {
+ int fd;
+ void *buf;
+ size_t count;
+} __attribute__((packed)) SYS_READ_PARAMS;
+
+typedef struct SYS_PWRITE_PARAMS {
+ int fd;
+ const void *buf;
+ size_t count;
+ size_t offset;
+} __attribute__((packed)) SYS_PWRITE_PARAMS;
+
+typedef struct SYS_WRITE_PARAMS {
+ int fd;
+ const void *buf;
+ size_t count;
+} __attribute__((packed)) SYS_WRITE_PARAMS;
+
+typedef struct SYS_EXEC_PARAMS {
+ const char *path;
+ char **argv;
+} __attribute__((packed)) SYS_EXEC_PARAMS;
+
+typedef struct SYS_DUP2_PARAMS {
+ int org_fd;
+ int new_fd;
+} __attribute__((packed)) SYS_DUP2_PARAMS;
+
+typedef struct SYS_OPENPTY_PARAMS {
+ int *amaster;
+ int *aslave;
+ char *name;
+ /*const struct termios*/ void *termp;
+ /*const struct winsize*/ void *winp;
+} __attribute__((packed)) SYS_OPENPTY_PARAMS;
+
+typedef struct SYS_POLL_PARAMS {
+ struct pollfd *fds;
+ size_t nfds;
+ int timeout;
+} __attribute__((packed)) SYS_POLL_PARAMS;
+
+typedef struct SYS_MMAP_PARAMS {
+ void *addr;
+ size_t length;
+ int prot;
+ int flags;
+ int fd;
+ size_t offset;
+} __attribute__((packed)) SYS_MMAP_PARAMS;
+
+typedef struct SYS_SOCKET_PARAMS {
+ int domain;
+ int type;
+ int protocol;
+} __attribute__((packed)) SYS_SOCKET_PARAMS;
+
+typedef struct SYS_BIND_PARAMS {
+ int sockfd;
+ const struct sockaddr *addr;
+ socklen_t addrlen;
+} __attribute__((packed)) SYS_BIND_PARAMS;
+
+typedef struct SYS_ACCEPT_PARAMS {
+ int socket;
+ struct sockaddr *address;
+ socklen_t *address_len;
+} __attribute__((packed)) SYS_ACCEPT_PARAMS;
+
+typedef struct SYS_SHM_OPEN_PARAMS {
+ const char *name;
+ int oflag;
+ mode_t mode;
+} __attribute__((packed)) SYS_SHM_OPEN_PARAMS;
+
+typedef struct SYS_FTRUNCATE_PARAMS {
+ int fildes;
+ size_t length;
+} __attribute__((packed)) SYS_FTRUNCATE_PARAMS;
+
+typedef struct SYS_STAT_PARAMS {
+ const char *pathname;
+ struct stat *statbuf;
+} __attribute__((packed)) SYS_STAT_PARAMS;
+#endif
diff --git a/userland/libc/include/syslog.h b/userland/libc/include/syslog.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/userland/libc/include/syslog.h
diff --git a/userland/libc/include/termios.h b/userland/libc/include/termios.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/userland/libc/include/termios.h
diff --git a/userland/libc/include/time.h b/userland/libc/include/time.h
new file mode 100644
index 0000000..567e9ef
--- /dev/null
+++ b/userland/libc/include/time.h
@@ -0,0 +1,35 @@
+#ifndef TIME_H
+#define TIME_H
+#include <sys/types.h>
+#include <stddef.h>
+
+#define CLOCK_REALTIME 0
+
+struct tm {
+ int tm_sec;
+ int tm_min;
+ int tm_hour;
+ int tm_mday;
+ int tm_mon;
+ int tm_year;
+ int tm_wday;
+ int tm_yday;
+ int tm_isdst;
+ long __tm_gmtoff;
+ const char *__tm_zone;
+};
+
+typedef int clockid_t;
+struct timespec {
+ time_t tv_sec; // Seconds.
+ long tv_nsec; // Nanoseconds.
+};
+
+time_t time(time_t *tloc);
+int clock_gettime(clockid_t clock_id, struct timespec *tp);
+struct tm *localtime(const time_t *timer);
+struct tm *gmtime(const time_t *timer);
+size_t strftime(char *restrict s, size_t maxsize,
+ const char *restrict format, const struct tm *restrict timeptr);
+char *ctime_r(const time_t *clock, char *buf);
+#endif
diff --git a/userland/libc/include/ubsan.h b/userland/libc/include/ubsan.h
new file mode 100644
index 0000000..dac5407
--- /dev/null
+++ b/userland/libc/include/ubsan.h
@@ -0,0 +1,79 @@
+#include <stdint.h>
+
+enum { type_kind_int = 0, type_kind_float = 1, type_unknown = 0xffff };
+
+struct type_descriptor {
+ uint16_t type_kind;
+ uint16_t type_info;
+ char type_name[1];
+};
+
+struct source_location {
+ const char *file_name;
+ union {
+ unsigned long reported;
+ struct {
+ uint32_t line;
+ uint32_t column;
+ };
+ };
+};
+
+struct OverflowData {
+ struct source_location location;
+ struct type_descriptor *type;
+};
+
+struct type_mismatch_data {
+ struct source_location location;
+ struct type_descriptor *type;
+ unsigned long alignment;
+ unsigned char type_check_kind;
+};
+
+struct type_mismatch_data_v1 {
+ struct source_location location;
+ struct type_descriptor *type;
+ unsigned char log_alignment;
+ unsigned char type_check_kind;
+};
+
+struct type_mismatch_data_common {
+ struct source_location *location;
+ struct type_descriptor *type;
+ unsigned long alignment;
+ unsigned char type_check_kind;
+};
+
+struct nonnull_arg_data {
+ struct source_location location;
+ struct source_location attr_location;
+ int arg_index;
+};
+
+struct OutOfBoundsData {
+ struct source_location location;
+ struct type_descriptor *array_type;
+ struct type_descriptor *index_type;
+};
+
+struct ShiftOutOfBoundsData {
+ struct source_location location;
+ struct type_descriptor *lhs_type;
+ struct type_descriptor *rhs_type;
+};
+
+struct unreachable_data {
+ struct source_location location;
+};
+
+struct invalid_value_data {
+ struct source_location location;
+ struct type_descriptor *type;
+};
+
+struct alignment_assumption_data {
+ struct source_location location;
+ struct source_location assumption_location;
+ struct type_descriptor *type;
+};
diff --git a/userland/libc/include/unistd.h b/userland/libc/include/unistd.h
new file mode 100644
index 0000000..e43dc33
--- /dev/null
+++ b/userland/libc/include/unistd.h
@@ -0,0 +1,24 @@
+#ifndef UNISTD_H
+#define UNISTD_H
+#include <stddef.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+#define STDIN_FILENO 0
+
+extern int opterr, optind, optopt;
+extern char *optarg;
+
+int close(int fildes);
+int ftruncate(int fildes, uint64_t length);
+int execv(char *path, char **argv);
+int pipe(int fd[2]);
+int dup2(int org_fd, int new_fd);
+int getopt(int argc, char *const argv[], const char *optstring);
+pid_t getpid(void);
+int unlink(const char *path);
+int execvp(const char *file, char *const argv[]);
+void _exit(int status);
+void msleep(uint32_t ms); // not standard
+uint32_t uptime(void); // not standard
+#endif
diff --git a/userland/libc/include/utime.h b/userland/libc/include/utime.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/userland/libc/include/utime.h
diff --git a/userland/libc/include/wchar.h b/userland/libc/include/wchar.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/userland/libc/include/wchar.h
diff --git a/userland/libc/include/wctype.h b/userland/libc/include/wctype.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/userland/libc/include/wctype.h
diff --git a/userland/libc/input.h b/userland/libc/input.h
new file mode 100644
index 0000000..a6602f5
--- /dev/null
+++ b/userland/libc/input.h
@@ -0,0 +1,9 @@
+#ifndef INPUT_H
+#define INPUT_H
+#include <stdint.h>
+
+struct input_event {
+ uint16_t key;
+ uint8_t status;
+};
+#endif
diff --git a/userland/libc/inttypes.h b/userland/libc/inttypes.h
new file mode 100644
index 0000000..0bf39d1
--- /dev/null
+++ b/userland/libc/inttypes.h
@@ -0,0 +1,5 @@
+#include <stdint.h>
+
+// FIXME: These are not correct
+#define PRId64 "d"
+#define PRId32 "d"
diff --git a/userland/libc/isspace.c b/userland/libc/isspace.c
new file mode 100644
index 0000000..9ba2766
--- /dev/null
+++ b/userland/libc/isspace.c
@@ -0,0 +1,5 @@
+#include <ctype.h>
+
+int isspace(int c) {
+ return c == ' ' || (unsigned)c-'\t' < 5;
+}
diff --git a/userland/libc/libc.c b/userland/libc/libc.c
new file mode 100644
index 0000000..259ef0c
--- /dev/null
+++ b/userland/libc/libc.c
@@ -0,0 +1,287 @@
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <syscall.h>
+
+int errno;
+
+char *errno_strings[] = {
+ "",
+ "Argument list too long.",
+ "Permission denied.",
+ "Address in use.",
+ "Address not available.",
+ "Address family not supported.",
+ "Resource unavailable, try again (may be the same value as [EWOULDBLOCK]).",
+ "Connection already in progress.",
+ "Bad file descriptor.",
+ "Bad message.",
+ "Device or resource busy.",
+ "Operation canceled.",
+ "No child processes.",
+ "Connection aborted.",
+ "Connection refused.",
+ "Connection reset.",
+ "Resource deadlock would occur.",
+ "Destination address required.",
+ "Mathematics argument out of domain of function.",
+ "Reserved.",
+ "File exists.",
+ "Bad address.",
+ "File too large.",
+ "Host is unreachable.",
+ "Identifier removed.",
+ "Illegal byte sequence.",
+ "Operation in progress.",
+ "Interrupted function.",
+ "Invalid argument.",
+ "I/O error.",
+ "Socket is connected.",
+ "Is a directory.",
+ "Too many levels of symbolic links.",
+ "File descriptor value too large.",
+ "Too many links.",
+ "Message too large.",
+ "Reserved.",
+ "Filename too long.",
+ "Network is down.",
+ "Connection aborted by network.",
+ "Network unreachable.",
+ "Too many files open in system.",
+ "No buffer space available.",
+ "No message is available on the STREAM head read "
+ "queue. [Option End]",
+ "No such device.",
+ "No such file or directory.",
+ "Executable file format error.",
+ "No locks available.",
+ "Reserved.",
+ "Not enough space.",
+ "No message of the desired type.",
+ "Protocol not available.",
+ "No space left on device.",
+ "No STREAM resources.",
+ "Not a STREAM.",
+ "Functionality not supported.",
+ "The socket is not connected.",
+ "Not a directory or a symbolic link to a directory.",
+ "Directory not empty.",
+ "State not recoverable.",
+ "Not a socket.",
+ "Not supported (may be the same value as [EOPNOTSUPP]).",
+ "Inappropriate I/O control operation.",
+ "No such device or address.",
+ "Operation not supported on socket (may be the same value as [ENOTSUP]).",
+ "Value too large to be stored in data type.",
+ "Previous owner died.",
+ "Operation not permitted.",
+ "Broken pipe.",
+ "Protocol error.",
+ "Protocol not supported.",
+ "Protocol wrong type for socket.",
+ "Result too large.",
+ "Read-only file system.",
+ "Invalid seek.",
+ "No such process.",
+ "Reserved.",
+ "Stream ioctl() timeout. [Option End]",
+ "Connection timed out.",
+ "Text file busy.",
+ "Operation would block (may be the same value as [EAGAIN]).",
+ "Cross-device link. ",
+};
+
+#define ASSERT_NOT_REACHED assert(0)
+
+#define TAB_SIZE 8
+
+// Functions preserve the registers ebx, esi, edi, ebp, and esp; while
+// eax, ecx, edx are scratch registers.
+
+// Syscall: eax ebx ecx edx esi edi
+int syscall(uint32_t eax, uint32_t ebx, uint32_t ecx, uint32_t edx,
+ uint32_t esi, uint32_t edi) {
+ asm volatile("push %edi\n"
+ "push %esi\n"
+ "push %ebx\n"
+ "mov 0x1C(%ebp), %edi\n"
+ "mov 0x18(%ebp), %esi\n"
+ "mov 0x14(%ebp), %edx\n"
+ "mov 0x10(%ebp), %ecx\n"
+ "mov 0xc(%ebp), %ebx\n"
+ "mov 0x8(%ebp), %eax\n"
+ "int $0x80\n"
+ "pop %ebx\n"
+ "pop %esi\n"
+ "pop %edi\n");
+}
+
+int pipe(int fd[2]) { return syscall(SYS_PIPE, fd, 0, 0, 0, 0); }
+
+// https://pubs.opengroup.org/onlinepubs/9699919799/functions/strerror.html
+char *strerror(int errnum) {
+ // The strerror() function shall map the error number in errnum to a
+ // locale-dependent error message string and shall return a pointer to it.
+ return errno_strings[errnum];
+}
+
+// https://pubs.opengroup.org/onlinepubs/9699919799/functions/perror.html
+void perror(const char *s) {
+ // The perror() function shall map the error number accessed through the
+ // symbol errno to a language-dependent error message, which shall be written
+ // to the standard error stream as follows:
+
+ // (First (if s is not a null pointer and the character pointed to
+ // by s is not the null byte),
+ if (s && *s != '\0') {
+ // the string pointed to by s
+ // followed by a <colon> and a <space>.
+ printf("%s: ", s);
+ }
+
+ // Then an error message string followed by a <newline>.
+ // The contents of the error message strings shall be the same as those
+ // returned by strerror() with argument errno.
+ printf("%s\n", strerror(errno));
+}
+
+int open(const char *file, int flags, int mode) {
+ struct SYS_OPEN_PARAMS args = {
+ .file = file,
+ .flags = flags,
+ .mode = mode,
+ };
+ RC_ERRNO(syscall(SYS_OPEN, &args, 0, 0, 0, 0));
+}
+
+int close(int fd) { return syscall(SYS_CLOSE, (void *)fd, 0, 0, 0, 0); }
+
+int execv(char *path, char **argv) {
+ struct SYS_EXEC_PARAMS args = {.path = path, .argv = argv};
+ return syscall(SYS_EXEC, &args, 0, 0, 0, 0);
+}
+/*
+int syscall(int sys, void *args) {
+ asm volatile("push %ebx\n"
+ "mov 0xc(%ebp), %ebx\n"
+ "mov 0x8(%ebp), %eax\n"
+ "int $0x80\n"
+ "pop %ebx\n");
+}*/
+
+int s_syscall(int sys) {
+ asm volatile("movl %0, %%eax\n"
+ "int $0x80\n" ::"r"((uint32_t)sys));
+}
+
+int write(int fd, const char *buf, size_t count) {
+ /*
+ struct SYS_WRITE_PARAMS args = {
+ .fd = fd,
+ .buf = buf,
+ .count = count,
+ };*/
+ return syscall(SYS_WRITE, fd, buf, count, 0, 0);
+}
+
+int pwrite(int fd, const char *buf, size_t count, size_t offset) {
+ struct SYS_PWRITE_PARAMS args = {
+ .fd = fd,
+ .buf = buf,
+ .count = count,
+ .offset = offset,
+ };
+ return syscall(SYS_PWRITE, &args, 0, 0, 0, 0);
+}
+
+int wait(int *stat_loc) { return syscall(SYS_WAIT, stat_loc, 0, 0, 0, 0); }
+
+void exit(int status) { syscall(SYS_EXIT, (void *)status, 0, 0, 0, 0); }
+
+int pread(int fd, void *buf, size_t count, size_t offset) {
+ struct SYS_PREAD_PARAMS args = {
+ .fd = fd,
+ .buf = buf,
+ .count = count,
+ .offset = offset,
+ };
+ RC_ERRNO(syscall(SYS_PREAD, &args, 0, 0, 0, 0));
+}
+
+int read(int fd, void *buf, size_t count) {
+ struct SYS_READ_PARAMS args = {
+ .fd = fd,
+ .buf = buf,
+ .count = count,
+ };
+ RC_ERRNO(syscall(SYS_READ, &args, 0, 0, 0, 0));
+}
+
+int dup2(int org_fd, int new_fd) {
+ struct SYS_DUP2_PARAMS args = {
+ .org_fd = org_fd,
+ .new_fd = new_fd,
+ };
+ RC_ERRNO(syscall(SYS_DUP2, &args, 0, 0, 0, 0));
+}
+
+int fork(void) { return s_syscall(SYS_FORK); }
+
+void dputc(int fd, const char c) { pwrite(fd, &c, 1, 0); }
+
+int brk(void *addr) { return syscall(SYS_BRK, addr, 0, 0, 0, 0); }
+
+void *sbrk(intptr_t increment) {
+ return (void *)syscall(SYS_SBRK, (void *)increment, 0, 0, 0, 0);
+}
+
+int poll(struct pollfd *fds, size_t nfds, int timeout) {
+ SYS_POLL_PARAMS args = {
+ .fds = fds,
+ .nfds = nfds,
+ .timeout = timeout,
+ };
+ RC_ERRNO(syscall(SYS_POLL, &args, 0, 0, 0, 0));
+}
+
+int socket(int domain, int type, int protocol) {
+ SYS_SOCKET_PARAMS args = {
+ .domain = domain,
+ .type = type,
+ .protocol = protocol,
+ };
+ RC_ERRNO(syscall(SYS_SOCKET, &args, 0, 0, 0, 0));
+}
+
+int accept(int socket, struct sockaddr *address, socklen_t *address_len) {
+ SYS_ACCEPT_PARAMS args = {
+ .socket = socket,
+ .address = address,
+ .address_len = address_len,
+ };
+ RC_ERRNO(syscall(SYS_ACCEPT, &args, 0, 0, 0, 0));
+}
+
+int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
+ SYS_BIND_PARAMS args = {
+ .sockfd = sockfd,
+ .addr = addr,
+ .addrlen = addrlen,
+ };
+ RC_ERRNO(syscall(SYS_BIND, &args, 0, 0, 0, 0));
+}
+
+int shm_open(const char *name, int oflag, mode_t mode) {
+ SYS_SHM_OPEN_PARAMS args = {
+ .name = name,
+ .oflag = oflag,
+ .mode = mode,
+ };
+ RC_ERRNO(syscall(SYS_SHM_OPEN, &args, 0, 0, 0, 0));
+}
+
+int ftruncate(int fildes, uint64_t length) {
+ SYS_FTRUNCATE_PARAMS args = {.fildes = fildes, .length = length};
+ RC_ERRNO(syscall(SYS_FTRUNCATE, &args, 0, 0, 0, 0));
+}
diff --git a/userland/libc/libgen/basename.c b/userland/libc/libgen/basename.c
new file mode 100644
index 0000000..a0a8adb
--- /dev/null
+++ b/userland/libc/libgen/basename.c
@@ -0,0 +1,45 @@
+#include <libgen.h>
+#include <stddef.h>
+
+/*
+The basename() function shall take the pathname pointed to by path and
+return a pointer to the final component of the pathname, deleting any
+trailing '/' characters.
+
+
+The basename() function may modify the string pointed to by path, and
+may return a pointer to internal storage. The returned pointer might be
+invalidated or the storage might be overwritten by a subsequent call to
+basename(). The returned pointer might also be invalidated if the
+calling thread is terminated.
+*/
+
+char *basename_empty_return_value = ".";
+char *basename_slash_return_value = "/";
+char *basename(char *path) {
+ // If path is a null pointer or points to an empty string, basename()
+ // shall return a pointer to the string ".".
+ if (NULL == path || '\0' == *path)
+ return basename_empty_return_value;
+
+ char *start = path;
+ // Move the string to the end
+ for (; *path; path++)
+ ;
+ if (start == path)
+ return start;
+ path--;
+ if ('/' == *path) // Trailing slash
+ *path = '\0';
+ // Loop until next slash is found
+ for (; path != start && '/' != *path; path--)
+ ;
+ // If the string pointed to by path consists entirely of the '/' character,
+ // basename() shall return a pointer to the string "/". If the string
+ // pointed to by path is exactly "//", it is implementation-defined whether
+ //'/' or "//" is returned.
+ path++;
+ if ('\0' == *path)
+ return basename_slash_return_value;
+ return path;
+}
diff --git a/userland/libc/libgen/dirname.c b/userland/libc/libgen/dirname.c
new file mode 100644
index 0000000..fb3c813
--- /dev/null
+++ b/userland/libc/libgen/dirname.c
@@ -0,0 +1,44 @@
+#include <libgen.h>
+
+char *dirname_empty_return_value = ".";
+char *dirname_slash_return_value = "/";
+char *dirname(char *path) {
+ // If path is a null pointer or points to an empty string,
+ // dirname() shall return a pointer to the string "."
+ if (!path)
+ return dirname_empty_return_value;
+ if ('\0' == *path)
+ return dirname_empty_return_value;
+
+ char *start = path;
+ for (; *path; path++)
+ ;
+ path--;
+ if ('/' == *path) {
+ if (start == path)
+ return path;
+ path--;
+ }
+
+ for (; path != start && '/' != *path; path--)
+ ;
+ // If path does not contain a '/', then dirname() shall return a pointer to
+ // the string ".".
+ if ('/' != *path)
+ return dirname_empty_return_value;
+
+ if (path == start)
+ return dirname_slash_return_value;
+
+ *path = '\0';
+ path--;
+
+ for (; path != start && '/' != *path; path--)
+ ;
+
+ if ('/' != *path)
+ return dirname_empty_return_value;
+
+ path++;
+ return path;
+}
diff --git a/userland/libc/limits.h b/userland/libc/limits.h
new file mode 100644
index 0000000..0c9389a
--- /dev/null
+++ b/userland/libc/limits.h
@@ -0,0 +1,2 @@
+#define PATH_MAX 256
+#define FILENAME_MAX PATH_MAX
diff --git a/userland/libc/malloc/malloc.c b/userland/libc/malloc/malloc.c
new file mode 100644
index 0000000..f351291
--- /dev/null
+++ b/userland/libc/malloc/malloc.c
@@ -0,0 +1,232 @@
+#include <assert.h>
+#include <errno.h>
+#include <malloc/malloc.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#define NEW_ALLOC_SIZE 0x20000
+#define MALLOC_HEADER_MAGIC 0x1337F00D
+#define MALLOC_HEADER_PAD 0x11223344
+
+#define IS_FREE (1 << 0)
+#define IS_FINAL (1 << 1)
+
+typedef struct MallocHeader {
+ uint32_t magic;
+ uint32_t size;
+ uint8_t flags;
+ struct MallocHeader *n;
+} MallocHeader;
+
+size_t max(size_t a, size_t b) { return (a > b) ? a : b; }
+
+//;size_t min(size_t a, size_t b) { return (a < b) ? a : b; }
+
+uint64_t delta_page(uint64_t a) { return 0x1000 - (a % 0x1000); }
+
+MallocHeader *head = NULL;
+MallocHeader *final = NULL;
+uint32_t total_heap_size = 0;
+
+int init_heap(void) {
+ head = (MallocHeader *)sbrk(NEW_ALLOC_SIZE);
+ if ((void *)-1 == head) {
+ perror("sbrk");
+ exit(1);
+ }
+ total_heap_size += NEW_ALLOC_SIZE - sizeof(MallocHeader);
+ head->magic = MALLOC_HEADER_MAGIC;
+ head->size = NEW_ALLOC_SIZE - sizeof(MallocHeader);
+ head->flags = IS_FREE | IS_FINAL;
+ head->n = NULL;
+ final = head;
+ return 1;
+}
+
+int add_heap_memory(size_t min_desired) {
+ min_desired += sizeof(MallocHeader) + 0x1000;
+ size_t allocation_size = max(min_desired, NEW_ALLOC_SIZE);
+ allocation_size += delta_page(allocation_size);
+ void *p;
+ if ((void *)(-1) == (p = (void *)sbrk(allocation_size))) {
+ perror("sbrk");
+ return 0;
+ }
+ total_heap_size += allocation_size - sizeof(MallocHeader);
+ void *e = final;
+ e = (void *)((uint32_t)e + final->size);
+ if (p == e) {
+ final->size += allocation_size - sizeof(MallocHeader);
+ return 1;
+ }
+ MallocHeader *new_entry = p;
+ new_entry->magic = MALLOC_HEADER_MAGIC;
+ new_entry->size = allocation_size - sizeof(MallocHeader);
+ new_entry->flags = IS_FREE | IS_FINAL;
+ new_entry->n = NULL;
+ final->n = new_entry;
+ final = new_entry;
+ return 1;
+}
+
+MallocHeader *next_header(MallocHeader *a) { return a->n; }
+
+MallocHeader *next_close_header(MallocHeader *a) {
+ if (!a) {
+ printf("next close header fail\n");
+ for (;;)
+ ;
+ }
+ if (a->flags & IS_FINAL)
+ return NULL;
+ return next_header(a);
+}
+
+MallocHeader *find_free_entry(uint32_t s, int align) {
+ // A new header is required as well as the newly allocated chunk
+ if (!head)
+ init_heap();
+ MallocHeader *p = head;
+ for (; p; p = next_header(p)) {
+ if (!(p->flags & IS_FREE))
+ continue;
+ uint64_t required_size = s;
+ if (align) {
+ void *addy = p;
+ addy = (void *)((uint32_t)addy + sizeof(MallocHeader));
+ uint64_t d = delta_page((uint32_t)addy);
+ if (d < sizeof(MallocHeader) && d != 0)
+ continue;
+ required_size += d;
+ }
+ if (p->size < required_size)
+ continue;
+ return p;
+ }
+ return NULL;
+}
+
+void merge_headers(MallocHeader *b) {
+ if (!(b->flags & IS_FREE))
+ return;
+
+ MallocHeader *n = next_close_header(b);
+ if (!n)
+ return;
+
+ if (n > 0xf58c0820 - 0x8 && n < 0xf58c0820 + 0x8) {
+ printf("b: %x\n", b);
+ printf("b->n: %x\n", b->n);
+ asm("hlt");
+ assert(0);
+ }
+ if (!(n->flags & IS_FREE))
+ return;
+
+ // Remove the next header and just increase the newly freed header
+ b->size += n->size;
+ b->flags |= n->flags & IS_FINAL;
+ b->n = n->n;
+ if (n == final)
+ final = b;
+}
+
+extern int errno;
+// https://pubs.opengroup.org/onlinepubs/9699919799/
+void *int_malloc(size_t s, int align) {
+ if (!head)
+ init_heap();
+ size_t n = s;
+ MallocHeader *free_entry = find_free_entry(s, align);
+ if (!free_entry) {
+ if (!add_heap_memory(s)) {
+ errno = ENOMEM;
+ printf("ENOMEM\n");
+ return NULL;
+ }
+ return int_malloc(s, align);
+ }
+
+ void *rc = (void *)((uint32_t)free_entry + sizeof(MallocHeader));
+
+ if (align) {
+ uint64_t d = delta_page((uint32_t)rc);
+ n = d;
+ n -= sizeof(MallocHeader);
+ }
+
+ // Create a new header
+ MallocHeader *new_entry =
+ (MallocHeader *)((uint32_t)free_entry + n + sizeof(MallocHeader));
+ new_entry->magic = MALLOC_HEADER_MAGIC;
+ new_entry->flags = free_entry->flags;
+ new_entry->n = free_entry->n;
+ new_entry->size = free_entry->size - n - sizeof(MallocHeader);
+ if (free_entry == final)
+ final = new_entry;
+ merge_headers(new_entry);
+
+ // Modify the free entry
+ free_entry->size = n;
+ free_entry->flags = 0;
+ free_entry->n = new_entry;
+
+ if (align && ((uint32_t)rc % 0x1000) != 0) {
+ void *c = int_malloc(s, 1);
+ free(rc);
+ rc = c;
+ return rc;
+ }
+ return rc;
+}
+
+void *malloc(size_t s) { return int_malloc(s + 1, 0); }
+
+// https://pubs.opengroup.org/onlinepubs/9699919799/
+void *calloc(size_t nelem, size_t elsize) {
+ // The calloc() function shall allocate unused space for an array of
+ // nelem elements each of whose size in bytes is elsize.
+ size_t alloc_size = nelem * elsize;
+ void *rc = malloc(alloc_size);
+ // The space shall be initialized to all bits 0.
+ memset(rc, 0, alloc_size);
+ return rc;
+}
+
+size_t get_mem_size(void *ptr) {
+ if (!ptr)
+ return 0;
+ return ((MallocHeader *)(ptr - sizeof(MallocHeader)))->size;
+}
+
+void *realloc(void *ptr, size_t size) {
+ void *rc = malloc(size);
+ if (!rc)
+ return NULL;
+ size_t l = get_mem_size(ptr);
+ size_t to_copy = min(l, size);
+ memcpy(rc, ptr, to_copy);
+ free(ptr);
+ return rc;
+}
+
+void free(void *p) {
+ if (!p)
+ return;
+ // FIXME: This assumes that p is at the start of a allocated area.
+ // Is this a assumption that can be made?
+ MallocHeader *h = (MallocHeader *)((uint32_t)p - sizeof(MallocHeader));
+ if (MALLOC_HEADER_MAGIC != h->magic) {
+ printf("h->magic: %x\n", h->magic);
+ printf("&h->magic: %x\n", &(h->magic));
+ assert(0);
+ }
+ if (h->flags & IS_FREE)
+ return;
+
+ h->flags |= IS_FREE;
+ merge_headers(h);
+}
diff --git a/userland/libc/malloc/malloc.h b/userland/libc/malloc/malloc.h
new file mode 100644
index 0000000..082d8ad
--- /dev/null
+++ b/userland/libc/malloc/malloc.h
@@ -0,0 +1,9 @@
+#ifndef MALLOC_H
+#define MALLOC_H
+#include <stdint.h>
+#include <stddef.h>
+
+void *malloc(size_t s);
+void *calloc(size_t nelem, size_t elsize);
+void free(void *p);
+#endif
diff --git a/userland/libc/malloc/oldmalloc.c b/userland/libc/malloc/oldmalloc.c
new file mode 100644
index 0000000..042049d
--- /dev/null
+++ b/userland/libc/malloc/oldmalloc.c
@@ -0,0 +1,136 @@
+#include "stdio.h"
+#include "stdlib.h"
+#include "../errno.h"
+#include <stdint.h>
+#include <stddef.h>
+#include <string.h>
+
+#define NEW_ALLOC_SIZE 0x1000
+
+#define IS_FREE (1 << 0)
+#define IS_FINAL (1 << 1)
+
+typedef struct MallocHeader {
+ uint32_t size;
+ uint8_t flags;
+} MallocHeader;
+
+MallocHeader *head = NULL;
+MallocHeader *final = NULL;
+uint32_t total_heap_size = 0;
+
+int init_heap(void) {
+ head = sbrk(NEW_ALLOC_SIZE);
+ if ((void *)-1 == head) {
+ // perror("sbrk");
+ return 0;
+ }
+ total_heap_size += NEW_ALLOC_SIZE;
+ head->size = NEW_ALLOC_SIZE;
+ head->flags = IS_FREE | IS_FINAL;
+ final = head;
+ return 1;
+}
+
+int add_heap_memory(void) {
+ if ((void *)-1 == sbrk(NEW_ALLOC_SIZE)) {
+ // perror("sbrk");
+ return 0;
+ }
+ total_heap_size += NEW_ALLOC_SIZE;
+ final->size += NEW_ALLOC_SIZE;
+ return 1;
+}
+
+MallocHeader *next_header(MallocHeader *a) {
+ if (a->flags & IS_FINAL)
+ return NULL;
+ return ((void *)a) + a->size;
+}
+
+MallocHeader *find_free_entry(uint32_t s) {
+ // A new header is required as well as the newly allocated chunk
+ s += sizeof(MallocHeader);
+ if (!head)
+ init_heap();
+ MallocHeader *p = head;
+ for (; p; p = next_header(p)) {
+ if (!(p->flags & IS_FREE))
+ continue;
+ if (p->size < s)
+ continue;
+ return p;
+ }
+ return NULL;
+}
+
+void merge_headers(MallocHeader *b) {
+ if (!(b->flags & IS_FREE))
+ return;
+
+ MallocHeader *n = next_header(b);
+ if (!n)
+ return;
+
+ if (!(n->flags & IS_FREE))
+ return;
+
+ // Remove the next header and just increase the newly freed header
+ b->size += n->size;
+ b->flags |= n->flags & IS_FINAL;
+ if (b->flags & IS_FINAL)
+ final = b;
+}
+
+extern int errno;
+// https://pubs.opengroup.org/onlinepubs/9699919799/
+void *malloc(size_t s) {
+ if(s == 0)
+ s = 1;
+
+ MallocHeader *free_entry = find_free_entry(s);
+ if (!free_entry) {
+ if (!add_heap_memory()) {
+ errno = ENOMEM;
+ return NULL;
+ }
+ return malloc(s);
+ }
+
+ // Create a new header
+ MallocHeader *new_entry = ((void *)free_entry) + s;
+ new_entry->flags |= IS_FREE;
+ new_entry->size = free_entry->size - s - sizeof(MallocHeader);
+ new_entry->flags |= free_entry->flags & IS_FINAL;
+ if (new_entry->flags & IS_FINAL)
+ final = new_entry;
+ merge_headers(new_entry);
+
+ // Modify the free entry
+ free_entry->size = s;
+ free_entry->flags = 0;
+
+ return ((void *)free_entry) + sizeof(MallocHeader);
+}
+
+// https://pubs.opengroup.org/onlinepubs/9699919799/
+void *calloc(size_t nelem, size_t elsize) {
+ // The calloc() function shall allocate unused space for an array of
+ // nelem elements each of whose size in bytes is elsize.
+ size_t alloc_size = nelem*elsize;
+ void *rc = malloc(alloc_size);
+ // The space shall be initialized to all bits 0.
+ memset(rc, 0, alloc_size);
+ return rc;
+}
+
+void free(void *p) {
+ // FIXME: This assumes that p is at the start of a allocated area.
+ // Is this a assumption that can be made?
+ MallocHeader *h = p - sizeof(MallocHeader);
+ if (h->flags & IS_FREE)
+ return;
+
+ h->flags |= IS_FREE;
+ merge_headers(h);
+}
diff --git a/userland/libc/math.h b/userland/libc/math.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/userland/libc/math.h
diff --git a/userland/libc/memset.c b/userland/libc/memset.c
new file mode 100644
index 0000000..51910e9
--- /dev/null
+++ b/userland/libc/memset.c
@@ -0,0 +1,15 @@
+#include <stddef.h>
+
+// https://pubs.opengroup.org/onlinepubs/9699919799/
+void *memset(void *s, int c, size_t n) {
+ // The memset() function shall copy c (converted to an unsigned
+ // char) into each of the first n bytes of the object pointed to by
+ // s.
+
+ unsigned char *p = s;
+ for (; n > 0; n--, p++)
+ *p = (unsigned char)c;
+
+ // The memset() function shall return s
+ return s;
+}
diff --git a/userland/libc/mmap.c b/userland/libc/mmap.c
new file mode 100644
index 0000000..06b79bd
--- /dev/null
+++ b/userland/libc/mmap.c
@@ -0,0 +1,19 @@
+#include <syscall.h>
+#include <errno.h>
+#include <sys/mman.h>
+
+extern int errno;
+
+void *mmap(void *addr, size_t length, int prot, int flags, int fd,
+ size_t offset) {
+ SYS_MMAP_PARAMS args = {
+ .addr = addr,
+ .length = length,
+ .prot = prot,
+ .flags = flags,
+ .fd = fd,
+ .offset = offset,
+ };
+// return (void*)syscall(SYS_MMAP, &args);
+ RC_ERRNO(syscall(SYS_MMAP, &args));
+}
diff --git a/userland/libc/poll.h b/userland/libc/poll.h
new file mode 100644
index 0000000..88e98b3
--- /dev/null
+++ b/userland/libc/poll.h
@@ -0,0 +1,16 @@
+#ifndef POLL_H
+#define POLL_H
+#include <stddef.h>
+
+#define POLLIN (1 << 0)
+#define POLLPRI (1 << 1)
+#define POLLOUT (1 << 2)
+
+struct pollfd {
+ int fd;
+ short events;
+ short revents;
+};
+
+int poll(struct pollfd *fds, size_t nfds, int timeout);
+#endif
diff --git a/userland/libc/pty.c b/userland/libc/pty.c
new file mode 100644
index 0000000..b7ddf00
--- /dev/null
+++ b/userland/libc/pty.c
@@ -0,0 +1,15 @@
+#include "pty.h"
+#include "syscall.h"
+
+int openpty(int *amaster, int *aslave, char *name,
+ /*const struct termios*/ void *termp,
+ /*const struct winsize*/ void *winp) {
+ SYS_OPENPTY_PARAMS args = {
+ .amaster = amaster,
+ .aslave = aslave,
+ .name = name,
+ .termp = termp,
+ .winp = winp,
+ };
+ syscall(SYS_OPENPTY, &args, 0, 0, 0, 0);
+}
diff --git a/userland/libc/pty.h b/userland/libc/pty.h
new file mode 100644
index 0000000..b8ce978
--- /dev/null
+++ b/userland/libc/pty.h
@@ -0,0 +1,6 @@
+#ifndef PTY_H
+#define PTY_H
+int openpty(int *amaster, int *aslave, char *name,
+ /*const struct termios*/ void *termp,
+ /*const struct winsize*/ void *winp);
+#endif
diff --git a/userland/libc/setjmp/longjmp.s b/userland/libc/setjmp/longjmp.s
new file mode 100644
index 0000000..8188f06
--- /dev/null
+++ b/userland/libc/setjmp/longjmp.s
@@ -0,0 +1,16 @@
+.global _longjmp
+.global longjmp
+.type _longjmp,@function
+.type longjmp,@function
+_longjmp:
+longjmp:
+ mov 4(%esp),%edx
+ mov 8(%esp),%eax
+ cmp $1,%eax
+ adc $0, %al
+ mov (%edx),%ebx
+ mov 4(%edx),%esi
+ mov 8(%edx),%edi
+ mov 12(%edx),%ebp
+ mov 16(%edx),%esp
+ jmp *20(%edx)
diff --git a/userland/libc/setjmp/setjmp.s b/userland/libc/setjmp/setjmp.s
new file mode 100644
index 0000000..4d19cf8
--- /dev/null
+++ b/userland/libc/setjmp/setjmp.s
@@ -0,0 +1,23 @@
+.global ___setjmp
+.hidden ___setjmp
+.global __setjmp
+.global _setjmp
+.global setjmp
+.type __setjmp,@function
+.type _setjmp,@function
+.type setjmp,@function
+___setjmp:
+__setjmp:
+_setjmp:
+setjmp:
+ mov 4(%esp), %eax
+ mov %ebx, (%eax)
+ mov %esi, 4(%eax)
+ mov %edi, 8(%eax)
+ mov %ebp, 12(%eax)
+ lea 4(%esp), %ecx
+ mov %ecx, 16(%eax)
+ mov (%esp), %ecx
+ mov %ecx, 20(%eax)
+ xor %eax, %eax
+ ret
diff --git a/userland/libc/socket.h b/userland/libc/socket.h
new file mode 100644
index 0000000..5e86b45
--- /dev/null
+++ b/userland/libc/socket.h
@@ -0,0 +1,41 @@
+#include <stddef.h>
+#include <stdint.h>
+
+#define AF_UNIX 0
+#define AF_LOCAL AF_UNIX
+
+#define INADDR_ANY 0
+
+typedef struct {
+ int domain;
+ int type;
+ int protocol;
+
+ // UNIX socket
+ char *path;
+ int incoming_fd;
+} SOCKET;
+
+typedef struct {
+ char *path;
+ SOCKET *s;
+} OPEN_UNIX_SOCKET;
+
+typedef uint32_t in_addr_t;
+typedef uint16_t in_port_t;
+typedef unsigned int sa_family_t;
+typedef uint32_t socklen_t;
+
+struct sockaddr {
+ sa_family_t sa_family; /* Address family */
+ char *sa_data; /* Socket address */
+};
+
+struct sockaddr_un {
+ sa_family_t sun_family; /* Address family */
+ char *sun_path; /* Socket pathname */
+};
+
+int socket(int domain, int type, int protocol);
+int accept(int socket, struct sockaddr *address, socklen_t *address_len);
+int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
diff --git a/userland/libc/stdio.h b/userland/libc/stdio.h
new file mode 100644
index 0000000..38aaf22
--- /dev/null
+++ b/userland/libc/stdio.h
@@ -0,0 +1,95 @@
+#ifndef STDIO_H
+#define STDIO_H
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdint.h>
+
+// FIXME: Most of these should probably not be here. But I am too lazy
+// to fix it right now. This is futures mees problem to deal wth.
+
+#define EOF (-1)
+
+#define SEEK_SET 0
+#define SEEK_CUR 1
+#define SEEK_END 2
+
+typedef struct __IO_FILE FILE;
+struct __IO_FILE {
+ size_t (*write)(FILE *, const unsigned char *, size_t);
+ size_t (*read)(FILE *, unsigned char *, size_t);
+ int (*seek)(FILE *, long, int);
+ long offset_in_file;
+ int buffered_char;
+ int has_buffered_char;
+ uint8_t is_eof;
+ uint8_t has_error;
+ uint64_t file_size;
+ void *cookie;
+};
+
+size_t write_fd(FILE *f, const unsigned char *s, size_t l);
+size_t read_fd(FILE *f, unsigned char *s, size_t l);
+int seek_fd(FILE *stream, long offset, int whence);
+
+typedef struct {
+ int fd;
+} FILE_FD_COOKIE;
+
+extern FILE __stdin_FILE;
+extern FILE __stdout_FILE;
+extern FILE __stderr_FILE;
+
+#define stdin (&__stdin_FILE)
+#define stdout (&__stdout_FILE)
+//#define stderr (&__stderr_FILE)
+#define stderr (&__stdout_FILE)
+
+typedef int mode_t;
+
+void perror(const char *s);
+
+int putchar(int c);
+int puts(const char *s);
+int brk(void *addr);
+void *sbrk(intptr_t increment);
+int write(int fd, const char *buf, size_t count);
+int pwrite(int fd, const char *buf, size_t count, size_t offset);
+int printf(const char *format, ...);
+int pread(int fd, void *buf, size_t count, size_t offset);
+int read(int fd, void *buf, size_t count);
+int fork(void);
+int memcmp(const void *s1, const void *s2, size_t n);
+int wait(int *stat_loc);
+void exit(int status);
+void *memcpy(void *dest, const void *src, uint32_t n);
+int shm_open(const char *name, int oflag, mode_t mode);
+int dprintf(int fd, const char *format, ...);
+int vdprintf(int fd, const char *format, va_list ap);
+int vprintf(const char *format, va_list ap);
+int snprintf(char *str, size_t size, const char *format, ...);
+int vsnprintf(char *str, size_t size, const char *format, va_list ap);
+int vfprintf(FILE *f, const char *fmt, va_list ap);
+int fgetc(FILE *stream);
+int getchar(void);
+#define getc(_a) fgetc(_a)
+size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
+size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
+FILE *fopen(const char *pathname, const char *mode);
+int fclose(FILE *stream);
+int fseek(FILE *stream, long offset, int whence);
+int fprintf(FILE *f, const char *fmt, ...);
+long strtol(const char *nptr, char **endptr, int base);
+char *strchr(const char *s, int c);
+char *strcat(char *s1, const char *s2);
+char *fgets(char *s, int n, FILE *stream);
+FILE *tmpfile(void);
+int feof(FILE *stream);
+int fscanf(FILE *stream, const char *format, ...);
+int ungetc(int c, FILE *stream);
+long ftell(FILE *stream);
+int fputc(int c, FILE *stream);
+int remove(const char *path);
+int ferror(FILE *stream);
+int fputs(const char *s, FILE *stream);
+int fflush(FILE *stream);
+#endif
diff --git a/userland/libc/stdio/dprintf.c b/userland/libc/stdio/dprintf.c
new file mode 100644
index 0000000..2f2aadb
--- /dev/null
+++ b/userland/libc/stdio/dprintf.c
@@ -0,0 +1,9 @@
+#include <stdio.h>
+
+int dprintf(int fd, const char *format, ...) {
+ va_list ap;
+ va_start(ap, format);
+ int rc = vdprintf(fd, format, ap);
+ va_end(ap);
+ return rc;
+}
diff --git a/userland/libc/stdio/fclose.c b/userland/libc/stdio/fclose.c
new file mode 100644
index 0000000..02d93ae
--- /dev/null
+++ b/userland/libc/stdio/fclose.c
@@ -0,0 +1,10 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+// https://pubs.opengroup.org/onlinepubs/9699919799/functions/fclose.html
+// FIXME: Do some actual error checking.
+int fclose(FILE *stream) {
+ free(stream->cookie);
+ free(stream);
+ return 0;
+}
diff --git a/userland/libc/stdio/feof.c b/userland/libc/stdio/feof.c
new file mode 100644
index 0000000..7f46301
--- /dev/null
+++ b/userland/libc/stdio/feof.c
@@ -0,0 +1,5 @@
+#include <stdio.h>
+
+int feof(FILE *stream) {
+ return stream->is_eof;
+}
diff --git a/userland/libc/stdio/ferror.c b/userland/libc/stdio/ferror.c
new file mode 100644
index 0000000..8cb46cf
--- /dev/null
+++ b/userland/libc/stdio/ferror.c
@@ -0,0 +1,5 @@
+#include <stdio.h>
+
+int ferror(FILE *stream) {
+ return stream->has_error;
+}
diff --git a/userland/libc/stdio/fflush.c b/userland/libc/stdio/fflush.c
new file mode 100644
index 0000000..7a37c79
--- /dev/null
+++ b/userland/libc/stdio/fflush.c
@@ -0,0 +1,7 @@
+#include <stdio.h>
+
+// https://pubs.opengroup.org/onlinepubs/9699919799/functions/fflush.html
+int fflush(FILE *stream) {
+ // FIXME: Implement
+ return 0;
+}
diff --git a/userland/libc/stdio/fgetc.c b/userland/libc/stdio/fgetc.c
new file mode 100644
index 0000000..c69211f
--- /dev/null
+++ b/userland/libc/stdio/fgetc.c
@@ -0,0 +1,20 @@
+#include <assert.h>
+#include <stdio.h>
+
+int fgetc(FILE *stream) {
+ if (stream->has_buffered_char) {
+ stream->has_buffered_char = 0;
+ return stream->buffered_char;
+ }
+ char c;
+ if (1 == fread(&c, 1, 1, stream))
+ return (int)c;
+ // FIXME: Should use feof and ferror
+ if (stream->has_error)
+ return EOF;
+ if (stream->is_eof)
+ return EOF;
+ // How did we get here?
+ assert(0);
+ return EOF;
+}
diff --git a/userland/libc/stdio/fgetpos.c b/userland/libc/stdio/fgetpos.c
new file mode 100644
index 0000000..7f34d6a
--- /dev/null
+++ b/userland/libc/stdio/fgetpos.c
@@ -0,0 +1,7 @@
+#include <stdio.h>
+
+// FIXME: Error handling
+int fgetpos(FILE *restrict stream, fpos_t *restrict pos) {
+ *pos = (fpos_t)stream->offset_in_file;
+ return 0;
+}
diff --git a/userland/libc/stdio/fgets.c b/userland/libc/stdio/fgets.c
new file mode 100644
index 0000000..8e21501
--- /dev/null
+++ b/userland/libc/stdio/fgets.c
@@ -0,0 +1,16 @@
+#include <stdio.h>
+
+char *fgets(char *s, int n, FILE *stream) {
+ for (int i = 0; i < n; i++) {
+ char c;
+ fread(&c, 1, 1, stream);
+ if (stream->has_error)
+ return NULL;
+ if (stream->is_eof)
+ return NULL;
+ s[i] = c;
+ if (c == '\n')
+ break;
+ }
+ return s;
+}
diff --git a/userland/libc/stdio/fileno.c b/userland/libc/stdio/fileno.c
new file mode 100644
index 0000000..246cc51
--- /dev/null
+++ b/userland/libc/stdio/fileno.c
@@ -0,0 +1,13 @@
+#include <stdio.h>
+#include <errno.h>
+
+// https://pubs.opengroup.org/onlinepubs/9699919799/functions/fileno.html
+// The fileno() function shall return the integer file descriptor associated
+// with the stream pointed to by stream.
+int fileno(FILE *stream) {
+ if (-1 == stream->fd) {
+ errno = EBADF;
+ return -1;
+ }
+ return stream->fd;
+}
diff --git a/userland/libc/stdio/fopen.c b/userland/libc/stdio/fopen.c
new file mode 100644
index 0000000..a29c7ef
--- /dev/null
+++ b/userland/libc/stdio/fopen.c
@@ -0,0 +1,57 @@
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <stdint.h>
+#include <stdio.h>
+
+// FIXME: All modes not implemented
+// https://pubs.opengroup.org/onlinepubs/9699919799/functions/fopen.html
+FILE *fopen(const char *pathname, const char *mode) {
+ uint8_t read = 0;
+ uint8_t write = 0;
+ uint8_t append = 0;
+ // FIXME: Not parsed correctly
+ for (; *mode; mode++) {
+ // r or rb
+ // Open file for reading.
+ // w or wb
+ // Truncate to zero length or create file for writing.
+ // a or ab
+ // Append; open or create file for writing at
+ // end-of-file.
+ switch (*mode) {
+ case 'r':
+ read = 1;
+ break;
+ case 'w':
+ write = 1;
+ break;
+ case 'a':
+ append = 1;
+ break;
+ }
+ }
+ int flag = 0;
+ if (read)
+ flag |= O_READ;
+ if (write)
+ flag |= O_WRITE;
+
+ int fd = open(pathname, flag, 0);
+ if (-1 == fd)
+ return NULL;
+
+ struct stat s;
+ stat(pathname, &s);
+
+ FILE *r = malloc(sizeof(FILE));
+ r->read = read_fd;
+ r->write = write_fd;
+ r->seek = seek_fd;
+ r->has_error = 0;
+ r->is_eof = 0;
+ r->offset_in_file = 0;
+ r->file_size = s.st_size;
+ r->cookie = NULL;
+ r->fd = fd;
+ return r;
+}
diff --git a/userland/libc/stdio/fprintf.c b/userland/libc/stdio/fprintf.c
new file mode 100644
index 0000000..f983065
--- /dev/null
+++ b/userland/libc/stdio/fprintf.c
@@ -0,0 +1,9 @@
+#include <stdio.h>
+
+int fprintf(FILE *f, const char *fmt, ...) {
+ va_list ap;
+ va_start(ap, fmt);
+ int rc = vfprintf(f, fmt, ap);
+ va_end(ap);
+ return rc;
+}
diff --git a/userland/libc/stdio/fputc.c b/userland/libc/stdio/fputc.c
new file mode 100644
index 0000000..7c8fa7c
--- /dev/null
+++ b/userland/libc/stdio/fputc.c
@@ -0,0 +1,7 @@
+#include <stdio.h>
+
+int fputc(int c, FILE *stream) {
+ if (fwrite(&c, 1, 1, stream) > 0)
+ return c;
+ return EOF;
+}
diff --git a/userland/libc/stdio/fputs.c b/userland/libc/stdio/fputs.c
new file mode 100644
index 0000000..1b70c66
--- /dev/null
+++ b/userland/libc/stdio/fputs.c
@@ -0,0 +1,9 @@
+#include <stdio.h>
+
+int fputs(const char *s, FILE *stream) {
+ const char *b = s;
+ for (; *s; s++)
+ if (0 == fwrite(s, 1, 1, stream))
+ return EOF;
+ return s - b;
+}
diff --git a/userland/libc/stdio/fread.c b/userland/libc/stdio/fread.c
new file mode 100644
index 0000000..1a27afa
--- /dev/null
+++ b/userland/libc/stdio/fread.c
@@ -0,0 +1,11 @@
+#include <stdio.h>
+#include <sys/types.h>
+
+size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream) {
+ // FIXME: Check for overflow
+ ssize_t bytes_to_read = nmemb * size;
+ size_t rc = stream->read(stream, ptr, bytes_to_read);
+ // On success, fread() return the number of items read
+ rc /= size;
+ return rc;
+}
diff --git a/userland/libc/stdio/fscanf.c b/userland/libc/stdio/fscanf.c
new file mode 100644
index 0000000..785ce4b
--- /dev/null
+++ b/userland/libc/stdio/fscanf.c
@@ -0,0 +1,7 @@
+#include <stdio.h>
+#include <assert.h>
+
+int fscanf(FILE *stream, const char *format, ...) {
+ // FIXME
+ assert(0);
+}
diff --git a/userland/libc/stdio/fseek.c b/userland/libc/stdio/fseek.c
new file mode 100644
index 0000000..fb891ec
--- /dev/null
+++ b/userland/libc/stdio/fseek.c
@@ -0,0 +1,21 @@
+#include <stdio.h>
+#include <assert.h>
+
+int fseek(FILE *stream, long offset, int whence) {
+ return stream->seek(stream, offset, whence);
+ /*
+ switch (whence) {
+ case SEEK_SET:
+ stream->offset_in_file = offset;
+ break;
+ case SEEK_CUR:
+ stream->offset_in_file += offset;
+ break;
+ case SEEK_END:
+ // FIXME
+ assert(0);
+ break;
+ }
+ // FIXME: Error checking
+ return 0;*/
+}
diff --git a/userland/libc/stdio/fsetpos.c b/userland/libc/stdio/fsetpos.c
new file mode 100644
index 0000000..c39c545
--- /dev/null
+++ b/userland/libc/stdio/fsetpos.c
@@ -0,0 +1,7 @@
+#include <stdio.h>
+
+// FIXME: Error handling
+int fsetpos(FILE *stream, const fpos_t *pos) {
+ stream->offset_in_file = (long)(*pos);
+ return 0;
+}
diff --git a/userland/libc/stdio/ftell.c b/userland/libc/stdio/ftell.c
new file mode 100644
index 0000000..35076d0
--- /dev/null
+++ b/userland/libc/stdio/ftell.c
@@ -0,0 +1,5 @@
+#include <stdio.h>
+
+long ftell(FILE *stream) {
+ return stream->offset_in_file;
+}
diff --git a/userland/libc/stdio/fwrite.c b/userland/libc/stdio/fwrite.c
new file mode 100644
index 0000000..552bbd6
--- /dev/null
+++ b/userland/libc/stdio/fwrite.c
@@ -0,0 +1,12 @@
+#include <stdio.h>
+#include <sys/types.h>
+
+size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) {
+ // FIXME: Check for overflow
+ ssize_t bytes_to_write = nmemb * size;
+ size_t rc = stream->write(stream, ptr, bytes_to_write);
+ // On success, fwrite() return the number of items
+ // written.
+ rc /= size;
+ return rc;
+}
diff --git a/userland/libc/stdio/getchar.c b/userland/libc/stdio/getchar.c
new file mode 100644
index 0000000..dad2263
--- /dev/null
+++ b/userland/libc/stdio/getchar.c
@@ -0,0 +1,4 @@
+#include <stdio.h>
+
+// The getchar() function shall be equivalent to getc(stdin).
+int getchar(void) { return fgetc(stdin); }
diff --git a/userland/libc/stdio/open_memstream.c b/userland/libc/stdio/open_memstream.c
new file mode 100644
index 0000000..8f359b9
--- /dev/null
+++ b/userland/libc/stdio/open_memstream.c
@@ -0,0 +1,108 @@
+#include <assert.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+/*
+struct __IO_FILE {
+ size_t (*write)(FILE *, const unsigned char *, size_t);
+ size_t (*read)(FILE *, unsigned char *, size_t);
+ int (*seek)(FILE *, long, int);
+ long offset_in_file;
+ int buffered_char;
+ int has_buffered_char;
+ int fd;
+ uint8_t is_eof;
+ uint8_t has_error;
+ uint64_t file_size;
+ void *cookie;
+};
+*/
+
+struct Memstream {
+ size_t buffer_usage;
+ char *buffer;
+};
+
+#define MEMSTREAM_DEF_SIZE 4096
+
+size_t memstream_write(FILE *fp, const unsigned char *buf, size_t n) {
+ struct Memstream *c = fp->cookie;
+ // FIXME: Do a reallocation
+ if (c->buffer_usage + n >= fp->file_size) {
+ n = fp->file_size - c->buffer_usage;
+ }
+
+ memcpy(c->buffer + fp->offset_in_file, buf, n);
+ fp->offset_in_file += n;
+ if (fp->offset_in_file > c->buffer_usage)
+ c->buffer_usage = fp->offset_in_file;
+ return n;
+}
+
+size_t memstream_read(FILE *fp, unsigned char *buf, size_t n) {
+ struct Memstream *c = fp->cookie;
+ size_t length_left = c->buffer_usage - fp->offset_in_file;
+ n = min(length_left, n);
+ memcpy(buf, c->buffer + fp->offset_in_file, n);
+ fp->offset_in_file += n;
+ if (0 == n)
+ fp->is_eof = 1;
+ return n;
+}
+
+int memstream_seek(FILE *stream, long offset, int whence) {
+ switch (whence) {
+ case SEEK_SET:
+ stream->offset_in_file = offset;
+ break;
+ case SEEK_CUR:
+ stream->offset_in_file += offset;
+ break;
+ case SEEK_END:
+ stream->offset_in_file = stream->file_size + offset;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ // FIXME: Error checking
+ return 0;
+}
+
+FILE *open_memstream(char **bufp, size_t *sizep) {
+ struct Memstream *c = NULL;
+ FILE *fp = malloc(sizeof(FILE));
+ if (!fp)
+ return NULL;
+
+ fp->offset_in_file = 0;
+ fp->buffered_char = 0;
+ fp->has_buffered_char = 0;
+ fp->seek = memstream_seek;
+ fp->fd = -1;
+ fp->is_eof = 0;
+ fp->has_error = 0;
+ fp->file_size = MEMSTREAM_DEF_SIZE;
+
+ fp->write = memstream_write;
+ fp->read = memstream_read;
+
+ c = malloc(sizeof(struct Memstream));
+ if (!c) {
+ goto _exit_memstream_fail;
+ }
+
+ fp->cookie = (void *)c;
+
+ c->buffer = *bufp = malloc(MEMSTREAM_DEF_SIZE);
+ if (!bufp) {
+ goto _exit_memstream_fail;
+ }
+ c->buffer_usage = 0;
+
+ return fp;
+_exit_memstream_fail:
+ free(c);
+ free(fp);
+ return NULL;
+}
diff --git a/userland/libc/stdio/printf.c b/userland/libc/stdio/printf.c
new file mode 100644
index 0000000..d26568a
--- /dev/null
+++ b/userland/libc/stdio/printf.c
@@ -0,0 +1,9 @@
+#include <stdio.h>
+
+int printf(const char *format, ...) {
+ va_list ap;
+ va_start(ap, format);
+ int rc = vprintf(format, ap);
+ va_end(ap);
+ return rc;
+}
diff --git a/userland/libc/stdio/putc.c b/userland/libc/stdio/putc.c
new file mode 100644
index 0000000..a468a95
--- /dev/null
+++ b/userland/libc/stdio/putc.c
@@ -0,0 +1,3 @@
+#include <stdio.h>
+
+int putc(int c, FILE *stream) { return fputc(c, stream);}
diff --git a/userland/libc/stdio/putchar.c b/userland/libc/stdio/putchar.c
new file mode 100644
index 0000000..3fcf7ca
--- /dev/null
+++ b/userland/libc/stdio/putchar.c
@@ -0,0 +1,7 @@
+#include <stdio.h>
+#include <unistd.h>
+
+int putchar(int c) {
+ printf("%c", (char)c);
+ return c;
+}
diff --git a/userland/libc/stdio/puts.c b/userland/libc/stdio/puts.c
new file mode 100644
index 0000000..4a72e66
--- /dev/null
+++ b/userland/libc/stdio/puts.c
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+int puts(const char *s) {
+ int rc = printf("%s\n", s);
+ return rc;
+}
diff --git a/userland/libc/stdio/remove.c b/userland/libc/stdio/remove.c
new file mode 100644
index 0000000..35b41ad
--- /dev/null
+++ b/userland/libc/stdio/remove.c
@@ -0,0 +1,9 @@
+#include <stdio.h>
+#include <errno.h>
+
+extern int errno;
+int remove(const char *path) {
+ // FIXME
+ errno = ENAMETOOLONG;
+ return -1;
+}
diff --git a/userland/libc/stdio/rename.c b/userland/libc/stdio/rename.c
new file mode 100644
index 0000000..15d4bf5
--- /dev/null
+++ b/userland/libc/stdio/rename.c
@@ -0,0 +1,8 @@
+#include <stdio.h>
+#include <assert.h>
+
+int rename(const char *old, const char *new) {
+ (void)old;
+ (void)new;
+ assert(0); // TODO: Implement
+ }
diff --git a/userland/libc/stdio/setvbuf.c b/userland/libc/stdio/setvbuf.c
new file mode 100644
index 0000000..7f91518
--- /dev/null
+++ b/userland/libc/stdio/setvbuf.c
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+int setvbuf(FILE *restrict stream, char *restrict buf, int type, size_t size) {
+ // TODO
+ return 0;
+}
diff --git a/userland/libc/stdio/snprintf.c b/userland/libc/stdio/snprintf.c
new file mode 100644
index 0000000..328442a
--- /dev/null
+++ b/userland/libc/stdio/snprintf.c
@@ -0,0 +1,42 @@
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+struct sn_cookie {
+ char *s;
+ size_t n;
+};
+
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+
+size_t sn_write(FILE *f, const unsigned char *s, const size_t l) {
+ struct sn_cookie *c = f->cookie;
+ size_t k = MIN(l, c->n);
+ memcpy(c->s, s, k);
+ c->s += k;
+ c->n -= k;
+ *(c->s) = '\0';
+ // Upon successful completion, the snprintf() function shall return the number
+ // of bytes that would be written to s had n been sufficiently large excluding
+ // the terminating null byte.
+ return l;
+}
+
+int vsnprintf(char *str, size_t size, const char *format, va_list ap) {
+ char dummy[1];
+ struct sn_cookie c = {.s = (size ? str : dummy), .n = (size ? size - 1 : 0)};
+ FILE f = {
+ .write = sn_write,
+ .cookie = &c,
+ };
+ return vfprintf(&f, format, ap);
+}
+
+int snprintf(char *str, size_t size, const char *format, ...) {
+ va_list ap;
+ va_start(ap, format);
+ int rc = vsnprintf(str, size, format, ap);
+ va_end(ap);
+ return rc;
+}
diff --git a/userland/libc/stdio/sprintf.c b/userland/libc/stdio/sprintf.c
new file mode 100644
index 0000000..deffbbe
--- /dev/null
+++ b/userland/libc/stdio/sprintf.c
@@ -0,0 +1,33 @@
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+struct s_cookie {
+ char *s;
+};
+
+size_t s_write(FILE *f, const unsigned char *s, size_t l) {
+ struct s_cookie *c = f->cookie;
+ memcpy(c->s, s, l);
+ c->s += l;
+ *(c->s) = '\0';
+ return l;
+}
+
+int vsprintf(char *str, const char *format, va_list ap) {
+ struct s_cookie c = {.s = str};
+ FILE f = {
+ .write = s_write,
+ .cookie = &c,
+ };
+ return vfprintf(&f, format, ap);
+}
+
+int sprintf(char *str, const char *format, ...) {
+ va_list ap;
+ va_start(ap, format);
+ int rc = vsprintf(str, format, ap);
+ va_end(ap);
+ return rc;
+}
diff --git a/userland/libc/stdio/stderr.c b/userland/libc/stdio/stderr.c
new file mode 100644
index 0000000..76597e2
--- /dev/null
+++ b/userland/libc/stdio/stderr.c
@@ -0,0 +1,11 @@
+#include <stdio.h>
+#include <unistd.h>
+
+FILE __stderr_FILE = {
+ .write = write_fd,
+ .read = read_fd,
+ .is_eof = 0,
+ .has_error = 0,
+ .cookie = NULL,
+ .fd = 2,
+};
diff --git a/userland/libc/stdio/stdin.c b/userland/libc/stdio/stdin.c
new file mode 100644
index 0000000..ae3ab8d
--- /dev/null
+++ b/userland/libc/stdio/stdin.c
@@ -0,0 +1,54 @@
+#include <assert.h>
+#include <stdio.h>
+#include <unistd.h>
+
+size_t write_fd(FILE *f, const unsigned char *s, size_t l) {
+ int rc = pwrite(f->fd, s, l, f->offset_in_file);
+ if (rc == -1) {
+ f->has_error = 1;
+ return 0;
+ }
+ f->offset_in_file += rc;
+ return rc;
+}
+
+size_t read_fd(FILE *f, unsigned char *s, size_t l) {
+ int rc = pread(f->fd, s, l, f->offset_in_file);
+ if (rc == 0)
+ f->is_eof = 1;
+ if (rc == -1) {
+ f->has_error = 1;
+ return 0;
+ }
+ f->offset_in_file += rc;
+ return rc;
+}
+
+int seek_fd(FILE *stream, long offset, int whence) {
+ switch (whence) {
+ case SEEK_SET:
+ stream->offset_in_file = offset;
+ break;
+ case SEEK_CUR:
+ stream->offset_in_file += offset;
+ break;
+ case SEEK_END:
+ stream->offset_in_file = stream->file_size + offset;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ // FIXME: Error checking
+ return 0;
+}
+
+FILE __stdin_FILE = {
+ .write = write_fd,
+ .read = read_fd,
+ .seek = NULL,
+ .is_eof = 0,
+ .has_error = 0,
+ .cookie = NULL,
+ .fd = 0,
+};
diff --git a/userland/libc/stdio/stdout.c b/userland/libc/stdio/stdout.c
new file mode 100644
index 0000000..7f4edf0
--- /dev/null
+++ b/userland/libc/stdio/stdout.c
@@ -0,0 +1,13 @@
+#include <stdio.h>
+#include <unistd.h>
+
+FILE __stdout_FILE = {
+ .write = write_fd,
+ .read = read_fd,
+ .is_eof = 0,
+ .has_error = 0,
+ .seek = NULL,
+ .cookie = NULL,
+ .fd = 1,
+};
+FILE __stderr_FILE;
diff --git a/userland/libc/stdio/tmpfile.c b/userland/libc/stdio/tmpfile.c
new file mode 100644
index 0000000..cee6e0a
--- /dev/null
+++ b/userland/libc/stdio/tmpfile.c
@@ -0,0 +1,9 @@
+#include <stdio.h>
+#include <assert.h>
+
+FILE *tmpfile(void) {
+ // TODO
+ printf("TODO: Implement tmpfile()\n");
+ assert(0);
+ return NULL;
+}
diff --git a/userland/libc/stdio/tmpnam.c b/userland/libc/stdio/tmpnam.c
new file mode 100644
index 0000000..aafe67d
--- /dev/null
+++ b/userland/libc/stdio/tmpnam.c
@@ -0,0 +1,10 @@
+#include <assert.h>
+#include <stdio.h>
+
+char *tmpnam(char *s) {
+ assert(!s);
+ s = malloc(100);
+ strcpy(s, "/tmp.XXXXXX");
+ mkstemp(s);
+ return s;
+}
diff --git a/userland/libc/stdio/ungetc.c b/userland/libc/stdio/ungetc.c
new file mode 100644
index 0000000..8d649bc
--- /dev/null
+++ b/userland/libc/stdio/ungetc.c
@@ -0,0 +1,9 @@
+#include <stdio.h>
+
+int ungetc(int c, FILE *stream) {
+ if (stream->has_buffered_char)
+ return EOF;
+ stream->buffered_char = c;
+ stream->has_buffered_char = 1;
+ return c;
+}
diff --git a/userland/libc/stdio/vdprintf.c b/userland/libc/stdio/vdprintf.c
new file mode 100644
index 0000000..b3fa065
--- /dev/null
+++ b/userland/libc/stdio/vdprintf.c
@@ -0,0 +1,77 @@
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+struct vd_cookie {
+ int fd;
+ char *buffer;
+ uint8_t buf_len;
+ uint8_t buf_used;
+ int sent_bytes;
+};
+
+size_t min(size_t a, size_t b) { return (a < b) ? a : b; }
+
+size_t vd_write(FILE *f, const unsigned char *s, size_t l) {
+ struct vd_cookie *c = f->cookie;
+
+ int clear_buffer = 0;
+ size_t b_copy = min(l, c->buf_len - (c->buf_used));
+ for (int i = 0; i < b_copy; i++) {
+ c->buffer[c->buf_used + i] = s[i];
+ if (s[i] == '\n')
+ clear_buffer = 1;
+ }
+ c->buf_used += b_copy;
+
+ if (clear_buffer) {
+ int rc = write(c->fd, c->buffer, c->buf_used);
+ c->buf_used = 0;
+ if (-1 == rc) {
+ return (size_t)-1;
+ }
+ c->sent_bytes += rc;
+ }
+ return l;
+}
+
+int vdprintf(int fd, const char *format, va_list ap) {
+ FILE f = {
+ .write = write_fd,
+ .fd = fd,
+ };
+ return vfprintf(&f, format, ap);
+ // return -1;
+ /*
+char buffer[32];
+struct vd_cookie c = {.fd = fd,
+ .buffer = buffer,
+ .buf_len = 32,
+ .buf_used = 0,
+ .sent_bytes = 0};
+FILE f = {
+.write = vd_write,
+.cookie = &c,
+};
+
+// If an output error was encountered, these functions shall return a
+// negative value and set errno to indicate the error.
+if (-1 == vfprintf(&f, format, ap))
+return -1;
+
+// Upon successful completion, the dprintf(),
+// fprintf(), and printf() functions shall return the number of bytes
+// transmitted.
+
+if(0 == c.buf_used)
+return c.sent_bytes;
+
+// First the current buffer needs to be cleared
+int rc = write(fd, buffer, c.buf_used);
+if (-1 == rc) {
+return -1;
+}
+c.sent_bytes += rc;
+return c.sent_bytes;*/
+}
diff --git a/userland/libc/stdio/vfprintf.c b/userland/libc/stdio/vfprintf.c
new file mode 100644
index 0000000..79a22fb
--- /dev/null
+++ b/userland/libc/stdio/vfprintf.c
@@ -0,0 +1,243 @@
+#include <assert.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+
+const char HEX_SET[0x10] = {'0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
+
+#define FILE_WRITE(_f, _s, _l, _r) \
+ { \
+ size_t _rc = _f->write(_f, (const unsigned char *)_s, _l); \
+ if ((size_t)-1 == _rc) \
+ assert(0); \
+ *(int *)(_r) += _rc; \
+ }
+// if ((size_t)0 == _rc) \
+// assert(0); \
+
+int fprint_num(FILE *f, int n, int base, char *char_set, int prefix,
+ int zero_padding, int right_padding) {
+ int c = 0;
+ if (0 == n) {
+ zero_padding = 1;
+ prefix = 1;
+ }
+ char str[32];
+ int i = 0;
+ for (; n != 0 && i < 32; i++, n /= base)
+ // str[i] = (n % base) + '0';
+ str[i] = char_set[(n % base)];
+
+ char t = (zero_padding) ? '0' : ' ';
+ int orig_i = i;
+
+ if (!right_padding) {
+ for (; prefix - orig_i > 0; prefix--)
+ FILE_WRITE(f, &t, 1, &c);
+ }
+
+ for (i--; i >= 0; i--)
+ FILE_WRITE(f, &(str[i]), 1, &c);
+
+ if (right_padding) {
+ for (; prefix - orig_i > 0; prefix--)
+ FILE_WRITE(f, &t, 1, &c);
+ }
+ return c;
+}
+
+int fprint_int(FILE *f, int n, int prefix, int zero_padding,
+ int right_padding) {
+ return fprint_num(f, n, 10, "0123456789", prefix, zero_padding,
+ right_padding);
+}
+
+int fprint_hex(FILE *f, int n, int prefix, int zero_padding,
+ int right_padding) {
+ return fprint_num(f, n, 16, "0123456789abcdef", prefix, zero_padding,
+ right_padding);
+}
+
+int fprint_octal(FILE *f, int n, int prefix, int zero_padding,
+ int right_padding) {
+ return fprint_num(f, n, 8, "012345678", prefix, zero_padding, right_padding);
+}
+
+int print_string(FILE *f, const char *s, int *rc, int prefix, int right_padding,
+ int precision) {
+ int l = strlen(s);
+ char t = ' ';
+ int c = 0;
+ if (!right_padding) {
+ if (prefix)
+ assert(-1 == precision); // FIXME: Is this correct?
+ for (; prefix - l > 0; prefix--)
+ FILE_WRITE(f, &t, 1, &c);
+ }
+ int bl = precision;
+ for (; *s; s++, (*rc)++) {
+ if (precision != -1) {
+ if (0 == bl)
+ break;
+ bl--;
+ }
+ int r;
+ FILE_WRITE(f, (const unsigned char *)s, 1, &r);
+ assert(r != 0);
+ }
+ if (right_padding) {
+ assert(-1 == precision); // FIXME: Is this correct?
+ for (; prefix - l > 0; prefix--)
+ FILE_WRITE(f, &t, 1, &c);
+ }
+ (*rc) += c;
+ return 0;
+}
+
+int parse_precision(const char **fmt) {
+ const char *s = *fmt;
+ int rc = 0;
+ for (int i = 0;; i++, s++) {
+ if ('\0' == *s)
+ break;
+ const char c = *s;
+ if ('*' == c) {
+ assert(i == 0);
+ return -1;
+ } else if (!(c >= '0' && c <= '9')) {
+ s--;
+ break;
+ }
+ rc *= 10;
+ rc += c - '0';
+ }
+ *fmt = s;
+ return rc;
+}
+
+int vfprintf(FILE *f, const char *fmt, va_list ap) {
+ int rc = 0;
+ const char *s = fmt;
+ int prefix = 0;
+
+ int zero_padding = 0;
+ int right_padding = 0;
+
+ int cont = 0;
+ int precision = -1;
+ for (; *s; s++) {
+ if (!cont && '%' != *s) {
+ FILE_WRITE(f, (const unsigned char *)s, 1, &rc);
+ continue;
+ }
+ if (!cont) {
+ cont = 1;
+ continue;
+ }
+
+ if ('\0' == *s)
+ break;
+
+ switch (*s) {
+ case '.':
+ s++;
+ assert('\0' != *s);
+ precision = parse_precision(&s);
+ assert('\0' != *s);
+ if (-1 == precision)
+ precision = va_arg(ap, int);
+ cont = 1;
+ break;
+ case '0':
+ prefix *= 10;
+ if (0 == prefix)
+ zero_padding = 1;
+ cont = 1;
+ break;
+ case '-':
+ assert(0 == prefix);
+ right_padding = 1;
+ cont = 1;
+ break;
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ prefix *= 10;
+ prefix += (*s) - '0';
+ cont = 1;
+ break;
+ case 'i':
+ case 'd':
+ if(-1 != precision) {
+ zero_padding = 1;
+ prefix = precision;
+ right_padding = 0;
+ }
+ rc += fprint_int(f, va_arg(ap, int), prefix, zero_padding, right_padding);
+ cont = 0;
+ break;
+ case 'u':
+ assert(-1 == precision);
+ rc += fprint_int(f, va_arg(ap, unsigned int), prefix, zero_padding,
+ right_padding);
+ cont = 0;
+ break;
+ case 's': {
+ assert(!zero_padding); // this is not supported to strings
+ char *a = va_arg(ap, char *);
+ if (!a) {
+ if (-1 ==
+ print_string(f, "(NULL)", &rc, prefix, right_padding, precision))
+ return -1;
+ cont = 0;
+ break;
+ }
+ if (-1 == print_string(f, a, &rc, prefix, right_padding, precision))
+ return -1;
+ cont = 0;
+ break;
+ }
+ case 'p': // TODO: Print this out in a nicer way
+ case 'x':
+ assert(-1 == precision);
+ rc += fprint_hex(f, va_arg(ap, const uint32_t), prefix, zero_padding,
+ right_padding);
+ cont = 0;
+ break;
+ case 'o':
+ assert(-1 == precision);
+ rc += fprint_octal(f, va_arg(ap, const uint32_t), prefix, zero_padding,
+ right_padding);
+ cont = 0;
+ break;
+ case '%': {
+ FILE_WRITE(f, (const unsigned char *)"%", 1, &rc);
+ cont = 0;
+ break;
+ }
+ case 'c': {
+ char c = va_arg(ap, const int);
+ FILE_WRITE(f, (const unsigned char *)&c, 1, &rc);
+ cont = 0;
+ break;
+ }
+ default:
+ printf("got %c but that is not supported by printf\n", *s);
+ assert(0);
+ break;
+ }
+ if (!cont) {
+ prefix = 0;
+ zero_padding = right_padding = 0;
+ precision = -1;
+ }
+ }
+ return rc;
+}
diff --git a/userland/libc/stdio/vprintf.c b/userland/libc/stdio/vprintf.c
new file mode 100644
index 0000000..8a8dc33
--- /dev/null
+++ b/userland/libc/stdio/vprintf.c
@@ -0,0 +1,3 @@
+#include <stdio.h>
+
+int vprintf(const char *format, va_list ap) { return vdprintf(1, format, ap); }
diff --git a/userland/libc/stdlib.h b/userland/libc/stdlib.h
new file mode 100644
index 0000000..bba5d84
--- /dev/null
+++ b/userland/libc/stdlib.h
@@ -0,0 +1,17 @@
+#ifndef STDLIB_H
+#define STDLIB_H
+#include <stddef.h>
+#include <limits.h>
+#define RAND_MAX (UINT32_MAX)
+
+void *malloc(size_t s);
+void *calloc(size_t nelem, size_t elsize);
+void *realloc(void *ptr, size_t size);
+void free(void *p);
+char *getenv(const char *name);
+int rand(void);
+void srand(unsigned int seed);
+unsigned long strtoul(const char *restrict str,
+ char **restrict endptr, int base);
+int atoi(const char *str);
+#endif
diff --git a/userland/libc/stdlib/abort.c b/userland/libc/stdlib/abort.c
new file mode 100644
index 0000000..7fd747e
--- /dev/null
+++ b/userland/libc/stdlib/abort.c
@@ -0,0 +1,10 @@
+#include <assert.h>
+#include <stdlib.h>
+
+// https://pubs.opengroup.org/onlinepubs/9699919799/functions/abort.html
+void abort(void) {
+ printf("aborting!!!!\n");
+ assert(0);
+ for (;;)
+ ;
+}
diff --git a/userland/libc/stdlib/abs.c b/userland/libc/stdlib/abs.c
new file mode 100644
index 0000000..1079beb
--- /dev/null
+++ b/userland/libc/stdlib/abs.c
@@ -0,0 +1,3 @@
+#include <stdlib.h>
+
+int abs(int i) { return (i < 0) ? (-i) : (i); }
diff --git a/userland/libc/stdlib/atexit.c b/userland/libc/stdlib/atexit.c
new file mode 100644
index 0000000..0e401ff
--- /dev/null
+++ b/userland/libc/stdlib/atexit.c
@@ -0,0 +1,6 @@
+#include <stdlib.h>
+
+int atexit(void (*func)(void)) {
+ //TODO
+ return 0;
+}
diff --git a/userland/libc/stdlib/atof.c b/userland/libc/stdlib/atof.c
new file mode 100644
index 0000000..8524f8b
--- /dev/null
+++ b/userland/libc/stdlib/atof.c
@@ -0,0 +1,5 @@
+#include <stdlib.h>
+
+double atof(const char *str) {
+ return strtod(str,(char **)NULL);
+}
diff --git a/userland/libc/stdlib/atoi.c b/userland/libc/stdlib/atoi.c
new file mode 100644
index 0000000..2183306
--- /dev/null
+++ b/userland/libc/stdlib/atoi.c
@@ -0,0 +1,4 @@
+#include <stdlib.h>
+
+// https://pubs.opengroup.org/onlinepubs/9699919799/
+int atoi(const char *str) { return (int)strtol(str, (char **)NULL, 10); }
diff --git a/userland/libc/stdlib/getenv.c b/userland/libc/stdlib/getenv.c
new file mode 100644
index 0000000..9a6a4e5
--- /dev/null
+++ b/userland/libc/stdlib/getenv.c
@@ -0,0 +1,6 @@
+#include <stdlib.h>
+
+char *getenv(const char *name) {
+ // FIXME
+ return NULL;
+}
diff --git a/userland/libc/stdlib/mkstemp.c b/userland/libc/stdlib/mkstemp.c
new file mode 100644
index 0000000..1ea8790
--- /dev/null
+++ b/userland/libc/stdlib/mkstemp.c
@@ -0,0 +1,14 @@
+#include <fcntl.h>
+#include <stdlib.h>
+
+char rand_char(void) { return 'A' + (rand() % 10); }
+
+int mkstemp(char *template) {
+ // FIXME: Incomplete
+ const char *s = template;
+ for (; *template; template ++) {
+ if ('X' == *template)
+ *template = rand_char();
+ }
+ return open(s, O_RDWR, O_CREAT);
+}
diff --git a/userland/libc/stdlib/qsort.c b/userland/libc/stdlib/qsort.c
new file mode 100644
index 0000000..3f87db5
--- /dev/null
+++ b/userland/libc/stdlib/qsort.c
@@ -0,0 +1,29 @@
+#include <stdlib.h>
+#include <string.h>
+
+// https://pubs.opengroup.org/onlinepubs/9699919799/functions/qsort.html
+void qsort(void *base, size_t nel, size_t width,
+ int (*compar)(const void *, const void *)) {
+ // If the nel argument has the value zero, the comparison function pointed to
+ // by compar shall not be called and no rearrangement shall take place.
+ if (0 == nel)
+ return;
+
+ // AB
+ // Results in negative
+ // BA
+ // Results in positive
+
+ // Using bubblesort
+ unsigned char *p = base;
+ for (size_t i = 1; i < nel; i++) {
+ for (size_t j = 0; j < nel; j++) {
+ if (compar((p + i * width), (p + j * width)) < 0) {
+ unsigned char tmp[width];
+ memcpy(tmp, (p + i * width), width);
+ memcpy((p + i * width), (p + j * width), width);
+ memcpy((p + j * width), tmp, width);
+ }
+ }
+ }
+}
diff --git a/userland/libc/stdlib/rand.c b/userland/libc/stdlib/rand.c
new file mode 100644
index 0000000..e186af7
--- /dev/null
+++ b/userland/libc/stdlib/rand.c
@@ -0,0 +1,17 @@
+#include <stdint.h>
+#include <stdlib.h>
+
+uint32_t xorshift(uint32_t x) {
+ uint32_t f = x;
+ x ^= x << 13;
+ x ^= x >> 17;
+ x ^= x << 5;
+ return f + x;
+}
+
+extern uint32_t __INTERNAL_RNG_STATE;
+int rand(void) {
+ uint32_t x = xorshift(__INTERNAL_RNG_STATE);
+ __INTERNAL_RNG_STATE++;
+ return x;
+}
diff --git a/userland/libc/stdlib/srand.c b/userland/libc/stdlib/srand.c
new file mode 100644
index 0000000..a35185a
--- /dev/null
+++ b/userland/libc/stdlib/srand.c
@@ -0,0 +1,8 @@
+#include <stdint.h>
+#include <stdlib.h>
+
+uint32_t __INTERNAL_RNG_STATE;
+void srand(unsigned int seed) {
+ __INTERNAL_RNG_STATE = seed;
+ __INTERNAL_RNG_STATE = rand(); // rand() used the internal rng state
+}
diff --git a/userland/libc/stdlib/strtod.c b/userland/libc/stdlib/strtod.c
new file mode 100644
index 0000000..2c83879
--- /dev/null
+++ b/userland/libc/stdlib/strtod.c
@@ -0,0 +1,70 @@
+#include <ctype.h>
+#include <stdlib.h>
+#include <assert.h>
+
+int ctoi(char c) { return c - '0'; }
+
+double strtod(const char *restrict nptr, char **restrict endptr) {
+ double r = 0;
+ // An initial, possibly empty, sequence of white-space characters (as
+ // specified by isspace())
+ for (; isspace(*nptr); nptr++)
+ ;
+
+ // A subject sequence interpreted as a floating-point constant or representing
+ // infinity or NaN
+
+ {
+ // The expected form of the subject sequence is an optional '+' or '-' sign
+ int sign = 0;
+ int exp_sign = 0;
+ if ('+' == *nptr) {
+ sign = 0;
+ nptr++;
+ } else if ('-' == *nptr) {
+ sign = 1;
+ nptr++;
+ }
+
+ // A non-empty sequence of decimal digits optionally containing a radix
+ // character
+ double exp = 0;
+ for (; isdigit(*nptr); nptr++) {
+ r *= 10;
+ r += ctoi(*nptr);
+ }
+ if ('.' == *nptr) {
+ double div = 10;
+ for (; isdigit(*nptr); nptr++) {
+ r += ctoi(*nptr) / div;
+ div *= 10;
+ }
+ }
+ r *= (sign) ? (-1) : (1);
+
+ // then an optional exponent part consisting of the character 'e' or
+ // the character 'E'
+ if ('e' == tolower(*nptr)) {
+ // optionally followed by a '+' or '-' character
+ if ('+' == *nptr) {
+ exp_sign = 0;
+ nptr++;
+ } else if ('-' == *nptr) {
+ exp_sign = 1;
+ nptr++;
+ }
+ // and then followed by one or more decimal digits
+ for (; isdigit(*nptr); nptr++) {
+ exp *= 10;
+ exp += ctoi(*nptr);
+ }
+ exp *= (exp_sign) ? (-1) : (1);
+ }
+ assert(0 == exp); // TODO
+ }
+
+ // A final string of one or more unrecognized characters, including the
+ // terminating NUL character of the input string
+ ;
+ return r;
+}
diff --git a/userland/libc/stdlib/strtol.c b/userland/libc/stdlib/strtol.c
new file mode 100644
index 0000000..7aa7760
--- /dev/null
+++ b/userland/libc/stdlib/strtol.c
@@ -0,0 +1,52 @@
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <assert.h>
+
+extern int errno;
+extern int get_value(char c, long base);
+
+// https://pubs.opengroup.org/onlinepubs/9699919799/functions/strtol.html
+long strtol(const char *str, char **restrict endptr, int base) {
+ long ret_value = 0;
+ if (endptr)
+ *endptr = str;
+ // Ignore inital white-space sequence
+ for (; *str && isspace(*str); str++)
+ ;
+ if (!*str)
+ return ret_value;
+
+ int sign = 0;
+ if ('-' == *str) {
+ // FIXME
+ sign = 1;
+ str++;
+ assert(0);
+ } else if ('+' == *str) {
+ str++;
+ }
+
+ if (0 == base) {
+ // FIXME
+ assert(0);
+ }
+
+ if (2 <= base && 36 >= base) {
+ for (; *str; str++) {
+ ret_value *= base;
+ int val = get_value(*str, base);
+ if (ret_value > LONG_MAX - val) {
+ errno = ERANGE;
+ return 0;
+ }
+ ret_value += val;
+ }
+ } else {
+ errno = EINVAL;
+ return 0;
+ }
+ if (endptr)
+ *endptr = str;
+ return ret_value;
+}
diff --git a/userland/libc/stdlib/strtold.c b/userland/libc/stdlib/strtold.c
new file mode 100644
index 0000000..222464e
--- /dev/null
+++ b/userland/libc/stdlib/strtold.c
@@ -0,0 +1,9 @@
+#include <assert.h>
+#include <stdlib.h>
+
+long double strtold(const char *restrict nptr, char **restrict endptr) {
+ // TODO
+ // I will do this some other day
+ assert(NULL);
+ return 0;
+}
diff --git a/userland/libc/stdlib/strtoul.c b/userland/libc/stdlib/strtoul.c
new file mode 100644
index 0000000..4d9a51d
--- /dev/null
+++ b/userland/libc/stdlib/strtoul.c
@@ -0,0 +1,72 @@
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <limits.h>
+
+extern int errno;
+int get_value(char c, long base) {
+ int r;
+ if (c >= '0' && c <= '9')
+ r = c - '0';
+ else if (c >= 'A' && c <= 'Z')
+ r = c - 'A';
+ else if (c >= 'a' && c <= 'z')
+ r = c - 'a';
+ else
+ return -1;
+ if (r >= base)
+ return -1;
+ return r;
+}
+
+// https://pubs.opengroup.org/onlinepubs/9699919799/functions/strtoul.html
+unsigned long strtoul(const char *restrict str, char **restrict endptr,
+ int base) {
+ unsigned long ret_value = 0;
+ if (endptr)
+ *endptr = str;
+ // Ignore inital white-space sequence
+ for (; *str && isspace(*str); str++)
+ ;
+ if (!*str)
+ return ret_value;
+
+ int sign = 0;
+ if ('-' == *str) {
+ // FIXME
+ sign = 1;
+ str++;
+ assert(0);
+ } else if ('+' == *str) {
+ str++;
+ }
+
+ if (0 == base) {
+ // FIXME
+ assert(0);
+ }
+
+ if (2 <= base && 36 >= base) {
+ for (; *str; str++) {
+ ret_value *= base;
+ int val = get_value(*str, base);
+ /*
+ if (-1 == val) {
+ errno = ERANGE;
+ return 0;
+ }*/
+ if (ret_value > ULONG_MAX - val) {
+ errno = ERANGE;
+ return 0;
+ }
+
+ ret_value += val;
+ }
+ } else {
+ errno = EINVAL;
+ return 0;
+ }
+ if (endptr)
+ *endptr = str;
+ return ret_value;
+}
diff --git a/userland/libc/stdlib/system.c b/userland/libc/stdlib/system.c
new file mode 100644
index 0000000..d951c5c
--- /dev/null
+++ b/userland/libc/stdlib/system.c
@@ -0,0 +1,17 @@
+#include <stdlib.h>
+
+int system(const char *command) {
+ if (!command)
+ return NULL;
+ int pid = fork();
+ if (0 == pid) {
+ char *argv[2];
+ argv[0] = "/sh";
+ argv[1] = command;
+ execv("/sh", argv);
+ }
+ // FIXME: Use waitpid
+ int rc;
+ (void)wait(&rc);
+ return rc;
+}
diff --git a/userland/libc/string.h b/userland/libc/string.h
new file mode 100644
index 0000000..f811dba
--- /dev/null
+++ b/userland/libc/string.h
@@ -0,0 +1,17 @@
+#ifndef STRING_H
+#define STRING_H
+#include <stddef.h>
+#include <stdint.h>
+
+char *strerror(int errnum);
+void *memset(void *s, int c, size_t n);
+void *memcpy(void *dest, const void *src, uint32_t n);
+int strcmp(const char *s1, const char *s2);
+char *strcpy(char *dest, const char *src);
+size_t strlen(const char *s);
+size_t strnlen(const char *s, size_t maxlen);
+int sscanf(const char *s, const char *restrict format, ...);
+char *strrchr(const char *s, int c);
+int strncmp(const char *s1, const char *s2, size_t n);
+char *strncpy(char *s1, const char *s2, size_t n);
+#endif
diff --git a/userland/libc/string/memcmp.c b/userland/libc/string/memcmp.c
new file mode 100644
index 0000000..01109b8
--- /dev/null
+++ b/userland/libc/string/memcmp.c
@@ -0,0 +1,11 @@
+#include <string.h>
+
+int memcmp(const void *s1, const void *s2, size_t n) {
+ int return_value = 0;
+
+ for (uint32_t i = 0; i < n; i++)
+ if (((unsigned char *)(s1))[i] != ((unsigned char *)(s2))[i])
+ return_value++;
+
+ return return_value;
+}
diff --git a/userland/libc/string/memcpy.c b/userland/libc/string/memcpy.c
new file mode 100644
index 0000000..e19dec9
--- /dev/null
+++ b/userland/libc/string/memcpy.c
@@ -0,0 +1,9 @@
+#include <string.h>
+
+void *memcpy(void *dest, const void *src, uint32_t n) {
+ unsigned char *d = dest;
+ const unsigned char *s = src;
+ for (; n; n--)
+ *d++ = *s++;
+ return dest;
+}
diff --git a/userland/libc/string/memmove.c b/userland/libc/string/memmove.c
new file mode 100644
index 0000000..5fc49f7
--- /dev/null
+++ b/userland/libc/string/memmove.c
@@ -0,0 +1,14 @@
+#include <string.h>
+
+// copy bytes in memory with overlapping areas
+// https://pubs.opengroup.org/onlinepubs/9699919799/functions/memmove.html
+void *memmove(void *s1, const void *s2, size_t n) {
+ // Copying takes place as if the n bytes from the object pointed to by s2 are
+ // first copied into a temporary array of n bytes that does not overlap the
+ // objects pointed to by s1 and s2, and then the n bytes from the temporary
+ // array are copied into the object pointed to by s1.
+ unsigned char tmp[n];
+ memcpy(tmp, s2, n);
+ memcpy(s1, tmp, n);
+ return s1;
+}
diff --git a/userland/libc/string/sscanf.c b/userland/libc/string/sscanf.c
new file mode 100644
index 0000000..28e1ce1
--- /dev/null
+++ b/userland/libc/string/sscanf.c
@@ -0,0 +1,193 @@
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+extern int errno;
+extern int get_value(char c, long base);
+
+long ftnum(FILE *stream, int base, int *error) {
+ char c;
+ long ret_value = 0;
+ *error = 0;
+ // Ignore inital white-space sequence
+ for (;;) {
+ if (EOF == (c = fgetc(stream))) {
+ *error = 1;
+ return 0;
+ }
+
+ if (!isspace(c)) {
+ ungetc(c, stream);
+ break;
+ }
+ }
+ if (c == '\0') {
+ *error = 1;
+ return 0;
+ }
+ if (!isdigit(c)) {
+ *error = 1;
+ return 0;
+ }
+ if (!(2 <= base && 36 >= base)) {
+ *error = 1;
+ return 0;
+ }
+ for (;;) {
+ if (EOF == (c = fgetc(stream)))
+ break;
+ if (c == '\0') {
+ ungetc(c, stream);
+ break;
+ }
+ int val = get_value(c, base);
+ if (-1 == val) {
+ ungetc(c, stream);
+ break;
+ }
+ if (ret_value * base > LONG_MAX - val) {
+ ungetc(c, stream);
+ errno = ERANGE;
+ *error = 1;
+ return 0;
+ }
+ ret_value *= base;
+ ret_value += val;
+ }
+ return ret_value;
+}
+
+int vfscanf(FILE *stream, const char *format, va_list ap) {
+ int rc = 0; // Upon successful completion, these functions shall return the
+ // number of successfully matched and assigned input items
+ int cont = 0;
+ int suppress = 0;
+ for (; *format; format++) {
+ if (*format != '%' && !cont) {
+ char c;
+ if (isspace(*format))
+ continue;
+ if (EOF == (c = fgetc(stream))) {
+ break;
+ }
+ if (*format == c) // TODO: Make sure this is the correct behaviour
+ continue;
+ // TODO: Make sure this is the correct behaviour
+ errno = EINVAL;
+ assert(0);
+ break;
+ }
+
+ if (*format == '%' && !cont) {
+ cont = 1;
+ continue;
+ }
+
+ int is_long = 0;
+ switch (*format) {
+ case 'l':
+ is_long++;
+ assert(is_long < 3);
+ cont = 1;
+ break;
+ case 'i': // Matches an optionally signed integer, whose format is the same
+ // as expected for the subject sequence of strtol() with 0 for the
+ // base argument.
+ case 'd': {
+ // Matches an optionally signed decimal integer, whose format is the
+ // same as expected for the subject sequence of strtol() with the value
+ // 10 for the base argument. In the absence of a size modifier, the
+ // application shall ensure that the corresponding argument is a pointer
+ // to int.
+ int err = 0;
+ int result = ftnum(stream, 10, &err);
+ if (err) {
+ cont = 0;
+ break;
+ }
+ if (!suppress) {
+ if (2 == is_long) {
+ *((long long *)va_arg(ap, long long *)) = result;
+ } else if (1 == is_long) {
+ *((long *)va_arg(ap, long *)) = result;
+ } else {
+ *((int *)va_arg(ap, int *)) = result;
+ }
+ rc++;
+ }
+ assert(0 == err);
+ cont = 0;
+ break;
+ }
+ case 'c': {
+ char result = fgetc(stream);
+ if (!suppress) {
+ *((char *)va_arg(ap, char *)) = result;
+ rc++;
+ }
+ cont = 0;
+ break;
+ }
+ case '*': // Assignment suppression
+ suppress = 1;
+ cont = 1;
+ break;
+ default:
+ printf("vfscanf: Got %c but not supported.\n", *format);
+ assert(0);
+ break;
+ }
+ if (!cont) {
+ suppress = 0;
+ }
+ }
+ return rc;
+}
+
+struct sscanf_cookie {
+ const char *s;
+};
+
+size_t sscanf_read(FILE *f, unsigned char *s, size_t l) {
+ struct sscanf_cookie *c = f->cookie;
+ if (!*(c->s)) {
+ return 0;
+ }
+ size_t r = 0;
+ for (; l && *(c->s); l--, c->s += 1) {
+ *s = *(c->s);
+ s++;
+ r++;
+ }
+ if (!(*(c->s)))
+ f->is_eof = 1;
+ /*
+ memcpy(s, c->s, l);
+ c->s += l;*/
+ return r;
+}
+
+int vsscanf(const char *s, const char *restrict format, va_list ap) {
+ struct sscanf_cookie c = {.s = s};
+ FILE f = {
+ .read = sscanf_read,
+ .cookie = &c,
+ .has_buffered_char = 0,
+ .is_eof = 0,
+ .has_error = 0,
+ .offset_in_file = 0,
+ };
+ return vfscanf(&f, format, ap);
+}
+
+int sscanf(const char *s, const char *restrict format, ...) {
+ va_list ap;
+ va_start(ap, format);
+ int rc = vsscanf(s, format, ap);
+ va_end(ap);
+ return rc;
+}
diff --git a/userland/libc/string/strcasecmp.c b/userland/libc/string/strcasecmp.c
new file mode 100644
index 0000000..eed337b
--- /dev/null
+++ b/userland/libc/string/strcasecmp.c
@@ -0,0 +1,28 @@
+#include <strings.h>
+
+int strcasecmp(const char *s1, const char *s2) {
+ // The strcmp() function shall compare the string pointed to by s1
+ // to the string pointed to by s2.
+ int l1, l2, rc;
+ l1 = l2 = rc = 0;
+ for (; (*s1 || *s2);) {
+ if (tolower(*s1) != tolower(*s2))
+ rc++;
+ if (*s1) {
+ l1++;
+ s1++;
+ }
+ if (*s2) {
+ l2++;
+ s2++;
+ }
+ }
+
+ // Upon completion, strcmp() shall return an integer greater than,
+ // equal to, or less than 0, if the string pointed to by s1 is
+ // greater than, equal to, or less than the string pointed to by
+ // s2, respectively.
+ if (l2 > l1)
+ return -rc;
+ return rc;
+}
diff --git a/userland/libc/string/strcat.c b/userland/libc/string/strcat.c
new file mode 100644
index 0000000..c430698
--- /dev/null
+++ b/userland/libc/string/strcat.c
@@ -0,0 +1,13 @@
+#include <string.h>
+
+char *strcat(char *s1, const char *s2) {
+ strcpy(s1 + strlen(s1), s2);
+ return s1;
+ /*
+char *r = s1;
+for (; *s1; s1++)
+;
+for (; *s2; s2++, s1++)
+*s1 = *s2;
+return r;*/
+}
diff --git a/userland/libc/string/strchr.c b/userland/libc/string/strchr.c
new file mode 100644
index 0000000..1995547
--- /dev/null
+++ b/userland/libc/string/strchr.c
@@ -0,0 +1,11 @@
+#include <string.h>
+
+char *strchr(const char *s, int c) {
+ for (; *s; s++) {
+ if (*s == (char)c)
+ return (char*)s;
+ }
+ if ((char)c == '\0')
+ return (char *)s;
+ return NULL;
+}
diff --git a/userland/libc/string/strcmp.c b/userland/libc/string/strcmp.c
new file mode 100644
index 0000000..368b8fb
--- /dev/null
+++ b/userland/libc/string/strcmp.c
@@ -0,0 +1,29 @@
+#include <string.h>
+
+// https://pubs.opengroup.org/onlinepubs/9699919799/
+int strcmp(const char *s1, const char *s2) {
+ // The strcmp() function shall compare the string pointed to by s1
+ // to the string pointed to by s2.
+ int l1, l2, rc;
+ l1 = l2 = rc = 0;
+ for (; *s1 || *s2;) {
+ if (*s1 != *s2)
+ rc++;
+ if (*s1) {
+ l1++;
+ s1++;
+ }
+ if (*s2) {
+ l2++;
+ s2++;
+ }
+ }
+
+ // Upon completion, strcmp() shall return an integer greater than,
+ // equal to, or less than 0, if the string pointed to by s1 is
+ // greater than, equal to, or less than the string pointed to by
+ // s2, respectively.
+ if (l2 > l1)
+ return -rc;
+ return rc;
+}
diff --git a/userland/libc/string/strcpy.c b/userland/libc/string/strcpy.c
new file mode 100644
index 0000000..9023fd1
--- /dev/null
+++ b/userland/libc/string/strcpy.c
@@ -0,0 +1,7 @@
+#include <string.h>
+
+char *strcpy(char *dest, const char *src) {
+ for (; (*dest = *src); dest++, src++)
+ ;
+ return dest;
+}
diff --git a/userland/libc/string/strcspn.c b/userland/libc/string/strcspn.c
new file mode 100644
index 0000000..2ad38d5
--- /dev/null
+++ b/userland/libc/string/strcspn.c
@@ -0,0 +1,14 @@
+#include <string.h>
+
+size_t strcspn(const char *s1, const char *s2) {
+ size_t r = 0;
+ for (; *s1; s1++) {
+ for (const char *t = s2; *t; t++) {
+ if (*s1 == *s2) {
+ r++;
+ break;
+ }
+ }
+ }
+ return r;
+}
diff --git a/userland/libc/string/strdup.c b/userland/libc/string/strdup.c
new file mode 100644
index 0000000..9e22f94
--- /dev/null
+++ b/userland/libc/string/strdup.c
@@ -0,0 +1,15 @@
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+// The strdup() function shall return a pointer to a new string, which is a
+// duplicate of the string pointed to by s. The returned pointer can be passed
+// to free(). A null pointer is returned if the new string cannot be created.
+char *strdup(const char *s) {
+ size_t l = strlen(s);
+ char *r = malloc(l + 1);
+ if (!r)
+ return NULL;
+ strcpy(r, s);
+ return r;
+}
diff --git a/userland/libc/string/strlcpy.c b/userland/libc/string/strlcpy.c
new file mode 100644
index 0000000..a2d3dd9
--- /dev/null
+++ b/userland/libc/string/strlcpy.c
@@ -0,0 +1,20 @@
+#include <string.h>
+
+// Copy string s2 to buffer s1 of size n. At most n-1
+// chars will be copied. Always NUL terminates (unless n == 0).
+// Returns strlen(s2); if retval >= n, truncation occurred.
+size_t *strlcpy(char *s1, const char *s2, size_t n) {
+ size_t tmp_n = n;
+ const char *os2 = s2;
+ for (; tmp_n; tmp_n--) {
+ if ((*s1++ = *s2++) == '\0')
+ break;
+ }
+ if (tmp_n == 0) {
+ if (n != 0)
+ *s1 = '\0'; /* NUL-terminate s1 */
+ while (*s2++)
+ ;
+ }
+ return s2 - os2 - 1;
+}
diff --git a/userland/libc/string/strlen.c b/userland/libc/string/strlen.c
new file mode 100644
index 0000000..8e3e77a
--- /dev/null
+++ b/userland/libc/string/strlen.c
@@ -0,0 +1,8 @@
+#include <string.h>
+
+size_t strlen(const char *s) {
+ const char *d = s;
+ for (; *s; s++)
+ ;
+ return s - d;
+}
diff --git a/userland/libc/string/strncasecmp.c b/userland/libc/string/strncasecmp.c
new file mode 100644
index 0000000..9ce8c04
--- /dev/null
+++ b/userland/libc/string/strncasecmp.c
@@ -0,0 +1,29 @@
+#include <strings.h>
+#include <stddef.h>
+
+int strncasecmp(const char *s1, const char *s2, size_t n) {
+ // The strcmp() function shall compare the string pointed to by s1
+ // to the string pointed to by s2.
+ int l1, l2, rc;
+ l1 = l2 = rc = 0;
+ for (; (*s1 || *s2) && n > 0; n--) {
+ if (tolower(*s1) != tolower(*s2))
+ rc++;
+ if (*s1) {
+ l1++;
+ s1++;
+ }
+ if (*s2) {
+ l2++;
+ s2++;
+ }
+ }
+
+ // Upon completion, strcmp() shall return an integer greater than,
+ // equal to, or less than 0, if the string pointed to by s1 is
+ // greater than, equal to, or less than the string pointed to by
+ // s2, respectively.
+ if (l2 > l1)
+ return -rc;
+ return rc;
+}
diff --git a/userland/libc/string/strncmp.c b/userland/libc/string/strncmp.c
new file mode 100644
index 0000000..fd46189
--- /dev/null
+++ b/userland/libc/string/strncmp.c
@@ -0,0 +1,28 @@
+#include <string.h>
+
+int strncmp(const char *s1, const char *s2, size_t n) {
+ // The strcmp() function shall compare the string pointed to by s1
+ // to the string pointed to by s2.
+ int l1, l2, rc;
+ l1 = l2 = rc = 0;
+ for (; (*s1 || *s2) && n > 0; n--) {
+ if (*s1 != *s2)
+ rc++;
+ if (*s1) {
+ l1++;
+ s1++;
+ }
+ if (*s2) {
+ l2++;
+ s2++;
+ }
+ }
+
+ // Upon completion, strcmp() shall return an integer greater than,
+ // equal to, or less than 0, if the string pointed to by s1 is
+ // greater than, equal to, or less than the string pointed to by
+ // s2, respectively.
+ if (l2 > l1)
+ return -rc;
+ return rc;
+}
diff --git a/userland/libc/string/strncpy.c b/userland/libc/string/strncpy.c
new file mode 100644
index 0000000..0e88c63
--- /dev/null
+++ b/userland/libc/string/strncpy.c
@@ -0,0 +1,13 @@
+#include <string.h>
+
+char *strncpy(char *s1, const char *s2, size_t n) {
+ char *rc = s1;
+ for (; n > 0; s1++, s2++, n--) {
+ *s1 = *s2;
+ if (!*s2)
+ break;
+ }
+ for (; n > 0; n--,s1++)
+ *s1 = '\0';
+ return rc;
+}
diff --git a/userland/libc/string/strndup.c b/userland/libc/string/strndup.c
new file mode 100644
index 0000000..ffb2088
--- /dev/null
+++ b/userland/libc/string/strndup.c
@@ -0,0 +1,22 @@
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+// The strndup() function shall be equivalent to the strdup() function,
+// duplicating the provided s in a new block of memory allocated as if
+// by using malloc(), with the exception being that strndup() copies at
+// most size plus one bytes into the newly allocated memory, terminating
+// the new string with a NUL character. If the length of s is larger
+// than size, only size bytes shall be duplicated. If size is larger
+// than the length of s, all bytes in s shall be copied into the new
+// memory buffer, including the terminating NUL character. The newly
+// created string shall always be properly terminated.
+char *strndup(const char *s, size_t size) {
+ size_t l = strlen(s);
+ size_t real_l = min(l, size);
+ char *r = malloc(real_l + 1);
+ if (!r)
+ return NULL;
+ strlcpy(r, s, real_l);
+ return r;
+}
diff --git a/userland/libc/string/strnlen.c b/userland/libc/string/strnlen.c
new file mode 100644
index 0000000..86df42e
--- /dev/null
+++ b/userland/libc/string/strnlen.c
@@ -0,0 +1,9 @@
+#include <string.h>
+
+size_t strnlen(const char *s, size_t maxlen) {
+ size_t i;
+ for (i = 0; i < maxlen; i++)
+ if (s[i] == 0)
+ break;
+ return i;
+}
diff --git a/userland/libc/string/strpbrk.c b/userland/libc/string/strpbrk.c
new file mode 100644
index 0000000..fb16b0c
--- /dev/null
+++ b/userland/libc/string/strpbrk.c
@@ -0,0 +1,12 @@
+#include <string.h>
+
+char *strpbrk(const char *s1, const char *s2) {
+ for (; *s1; s1++) {
+ for (const char *t = s2; *t; t++) {
+ if (*s1 == *t) {
+ return s1;
+ }
+ }
+ }
+ return NULL;
+}
diff --git a/userland/libc/string/strrchr.c b/userland/libc/string/strrchr.c
new file mode 100644
index 0000000..a44199a
--- /dev/null
+++ b/userland/libc/string/strrchr.c
@@ -0,0 +1,12 @@
+#include <string.h>
+
+char *strrchr(const char *s, int c) {
+ char *last = NULL;
+ for (; *s; s++) {
+ if (*s == (char)c)
+ last = (char *)s;
+ }
+ if ((char)c == '\0')
+ last = (char*)s;
+ return last;
+}
diff --git a/userland/libc/string/strspn.c b/userland/libc/string/strspn.c
new file mode 100644
index 0000000..2a7d3ae
--- /dev/null
+++ b/userland/libc/string/strspn.c
@@ -0,0 +1,18 @@
+#include <string.h>
+
+size_t strspn(const char *s1, const char *s2) {
+ size_t r = 0;
+ for (; *s1; s1++) {
+ int e = 0;
+ for (const char *t = s2; *t; t++) {
+ if (*s1 == *t) {
+ e = 1;
+ break;
+ }
+ }
+ if (!e)
+ break;
+ r++;
+ }
+ return r;
+}
diff --git a/userland/libc/string/strstr.c b/userland/libc/string/strstr.c
new file mode 100644
index 0000000..20b9dc2
--- /dev/null
+++ b/userland/libc/string/strstr.c
@@ -0,0 +1,21 @@
+#include <string.h>
+
+char *strstr(const char *s1, const char *s2) {
+ // If s2 points to a string with zero length, the function shall return s1.
+ if ('\0' == *s2)
+ return s1;
+ for (; *s1; s1++) {
+ const char *t1 = s1;
+ const char *t2 = s2;
+ int is_dif = 0;
+ for (; *t2 && *t1; t1++, t2++) {
+ if (*t2 != *t1) {
+ is_dif = 1;
+ break;
+ }
+ }
+ if (!is_dif)
+ return s1;
+ }
+ return NULL;
+}
diff --git a/userland/libc/string/strtok.c b/userland/libc/string/strtok.c
new file mode 100644
index 0000000..7b8d0e3
--- /dev/null
+++ b/userland/libc/string/strtok.c
@@ -0,0 +1,26 @@
+#include <string.h>
+
+char *strtok_s;
+
+char *strtok(char *restrict s, const char *restrict sep) {
+ if (s) {
+ strtok_s = s;
+ return strtok(NULL, sep);
+ }
+ if(!strtok_s)
+ return NULL;
+ char *e = strpbrk(strtok_s, sep);
+ if (!e) {
+ char *r = strtok_s;
+ strtok_s = NULL;
+ return r;
+ }
+ *e = '\0';
+ e--;
+ for (; *sep; sep++)
+ e++;
+ e++;
+ char *r = strtok_s;
+ strtok_s = e;
+ return r;
+}
diff --git a/userland/libc/strings.h b/userland/libc/strings.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/userland/libc/strings.h
diff --git a/userland/libc/sys/mman.h b/userland/libc/sys/mman.h
new file mode 100644
index 0000000..e3ff734
--- /dev/null
+++ b/userland/libc/sys/mman.h
@@ -0,0 +1,8 @@
+#ifndef MMAP_H
+#define MMAP_H
+#include <stdint.h>
+#include <stddef.h>
+
+void *mmap(void *addr, size_t length, int prot, int flags, int fd,
+ size_t offset);
+#endif
diff --git a/userland/libc/sys/mman/mmap.c b/userland/libc/sys/mman/mmap.c
new file mode 100644
index 0000000..b9ad3a2
--- /dev/null
+++ b/userland/libc/sys/mman/mmap.c
@@ -0,0 +1,19 @@
+#include <syscall.h>
+#include <errno.h>
+#include <sys/mman.h>
+
+extern int errno;
+
+void *mmap(void *addr, size_t length, int prot, int flags, int fd,
+ size_t offset) {
+ SYS_MMAP_PARAMS args = {
+ .addr = addr,
+ .length = length,
+ .prot = prot,
+ .flags = flags,
+ .fd = fd,
+ .offset = offset,
+ };
+// return (void*)syscall(SYS_MMAP, &args, 0, 0, 0, 0);
+ RC_ERRNO(syscall(SYS_MMAP, &args, 0, 0, 0, 0));
+}
diff --git a/userland/libc/sys/stat.h b/userland/libc/sys/stat.h
new file mode 100644
index 0000000..2fe6cdc
--- /dev/null
+++ b/userland/libc/sys/stat.h
@@ -0,0 +1,30 @@
+#ifndef STAT_H
+#define STAT_H
+#include <sys/types.h>
+#include <time.h>
+
+struct stat {
+ dev_t st_dev; // Device ID of device containing file.
+ ino_t st_ino; // File serial number.
+ mode_t st_mode; // Mode of file (see below).
+ nlink_t st_nlink; // Number of hard links to the file.
+ uid_t st_uid; // User ID of file.
+ gid_t st_gid; // Group ID of file.
+ dev_t st_rdev; // Device ID (if file is character or block special).
+ off_t st_size; // For regular files, the file size in bytes.
+ // For symbolic links, the length in bytes of the
+ // pathname contained in the symbolic link.
+ // For a shared memory object, the length in bytes.
+ // For a typed memory object, the length in bytes.
+ // For other file types, the use of this field is
+ // unspecified.
+ struct timespec st_atime; // Last data access timestamp.
+ struct timespec st_mtime; // Last data modification timestamp.
+ struct timespec st_ctime; // Last file status change timestamp.
+ blksize_t st_blksize; // A file system-specific preferred I/O block size
+ // for this object. In some file system types, this
+ // may vary from file to file.
+ blkcnt_t st_blocks; // Number of blocks allocated for this object.
+};
+int stat(const char *path, struct stat *buf);
+#endif
diff --git a/userland/libc/sys/stat/mkdir.c b/userland/libc/sys/stat/mkdir.c
new file mode 100644
index 0000000..c057fa7
--- /dev/null
+++ b/userland/libc/sys/stat/mkdir.c
@@ -0,0 +1,9 @@
+#include <sys/stat.h>
+#include <assert.h>
+
+int mkdir(const char *path, mode_t mode) {
+ (void)path;
+ (void)mode;
+ assert(0); // TODO: Implement
+ return 0;
+}
diff --git a/userland/libc/sys/stat/stat.c b/userland/libc/sys/stat/stat.c
new file mode 100644
index 0000000..e37223e
--- /dev/null
+++ b/userland/libc/sys/stat/stat.c
@@ -0,0 +1,13 @@
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <syscall.h>
+
+int stat(const char *path, struct stat *buf) {
+ SYS_STAT_PARAMS args = {
+ .pathname = path,
+ .statbuf = buf,
+ };
+ RC_ERRNO(syscall(SYS_STAT, &args, 0, 0, 0, 0));
+}
diff --git a/userland/libc/sys/time/gettimeofday.c b/userland/libc/sys/time/gettimeofday.c
new file mode 100644
index 0000000..e172cf2
--- /dev/null
+++ b/userland/libc/sys/time/gettimeofday.c
@@ -0,0 +1,5 @@
+#include <sys/time.h>
+#include <time.h>
+
+static int return_tod =0;
+int gettimeofday(struct timeval *tp, void *tzp) {return return_tod++;}
diff --git a/userland/libc/sys/types.h b/userland/libc/sys/types.h
new file mode 100644
index 0000000..ffcf281
--- /dev/null
+++ b/userland/libc/sys/types.h
@@ -0,0 +1,27 @@
+#ifndef TYPES_H
+#define TYPES_H
+typedef unsigned int ino_t;
+
+typedef int mode_t;
+
+typedef int nlink_t;
+typedef int uid_t;
+typedef int gid_t;
+typedef int id_t;
+
+typedef int blkcnt_t;
+typedef int off_t;
+
+typedef int dev_t;
+typedef unsigned int fsblkcnt_t;
+typedef unsigned int fsfilcnt_t;
+typedef unsigned int ino_t;
+//typedef unsigned int size_t;
+
+typedef int blksize_t;
+typedef int pid_t;
+typedef int ssize_t;
+
+//typedef int clock_t;
+typedef int time_t;
+#endif
diff --git a/userland/libc/syscall.h b/userland/libc/syscall.h
new file mode 100644
index 0000000..952492f
--- /dev/null
+++ b/userland/libc/syscall.h
@@ -0,0 +1,149 @@
+#ifndef SYSCALL_H
+#define SYSCALL_H
+#include "socket.h"
+#include <stddef.h>
+#include <stdint.h>
+
+#define SYS_OPEN 0
+#define SYS_READ 1
+#define SYS_WRITE 2
+#define SYS_PREAD 3
+#define SYS_PWRITE 4
+#define SYS_FORK 5
+#define SYS_EXEC 6
+#define SYS_GETPID 7
+#define SYS_EXIT 8
+#define SYS_WAIT 9
+#define SYS_BRK 10
+#define SYS_SBRK 11
+#define SYS_PIPE 12
+#define SYS_DUP2 13
+#define SYS_CLOSE 14
+#define SYS_OPENPTY 15
+#define SYS_POLL 16
+#define SYS_MMAP 17
+#define SYS_ACCEPT 18
+#define SYS_BIND 19
+#define SYS_SOCKET 20
+#define SYS_SHM_OPEN 21
+#define SYS_FTRUNCATE 22
+#define SYS_STAT 23
+#define SYS_MSLEEP 24
+#define SYS_UPTIME 25
+
+int syscall(uint32_t eax, uint32_t ebx, uint32_t ecx, uint32_t edx,
+ uint32_t esi, uint32_t edi);
+int s_syscall(int sys);
+
+extern int errno;
+#define RC_ERRNO(_rc) \
+ { \
+ int c = _rc; \
+ if (c < 0) { \
+ errno = -(c); \
+ return -1; \
+ } \
+ return c; \
+ }
+
+typedef int mode_t;
+
+typedef struct SYS_OPEN_PARAMS {
+ char *file;
+ int flags;
+ int mode;
+} __attribute__((packed)) SYS_OPEN_PARAMS;
+
+typedef struct SYS_PREAD_PARAMS {
+ int fd;
+ void *buf;
+ size_t count;
+ size_t offset;
+} __attribute__((packed)) SYS_PREAD_PARAMS;
+
+typedef struct SYS_READ_PARAMS {
+ int fd;
+ void *buf;
+ size_t count;
+} __attribute__((packed)) SYS_READ_PARAMS;
+
+typedef struct SYS_PWRITE_PARAMS {
+ int fd;
+ void *buf;
+ size_t count;
+ size_t offset;
+} __attribute__((packed)) SYS_PWRITE_PARAMS;
+
+typedef struct SYS_WRITE_PARAMS {
+ int fd;
+ void *buf;
+ size_t count;
+} __attribute__((packed)) SYS_WRITE_PARAMS;
+
+typedef struct SYS_EXEC_PARAMS {
+ char *path;
+ char **argv;
+} __attribute__((packed)) SYS_EXEC_PARAMS;
+
+typedef struct SYS_DUP2_PARAMS {
+ int org_fd;
+ int new_fd;
+} __attribute__((packed)) SYS_DUP2_PARAMS;
+
+typedef struct SYS_OPENPTY_PARAMS {
+ int *amaster;
+ int *aslave;
+ char *name;
+ /*const struct termios*/ void *termp;
+ /*const struct winsize*/ void *winp;
+} __attribute__((packed)) SYS_OPENPTY_PARAMS;
+
+typedef struct SYS_POLL_PARAMS {
+ struct pollfd *fds;
+ size_t nfds;
+ int timeout;
+} __attribute__((packed)) SYS_POLL_PARAMS;
+
+typedef struct SYS_MMAP_PARAMS {
+ void *addr;
+ size_t length;
+ int prot;
+ int flags;
+ int fd;
+ size_t offset;
+} __attribute__((packed)) SYS_MMAP_PARAMS;
+
+typedef struct SYS_SOCKET_PARAMS {
+ int domain;
+ int type;
+ int protocol;
+} __attribute__((packed)) SYS_SOCKET_PARAMS;
+
+typedef struct SYS_BIND_PARAMS {
+ int sockfd;
+ const struct sockaddr *addr;
+ socklen_t addrlen;
+} __attribute__((packed)) SYS_BIND_PARAMS;
+
+typedef struct SYS_ACCEPT_PARAMS {
+ int socket;
+ struct sockaddr *address;
+ socklen_t *address_len;
+} __attribute__((packed)) SYS_ACCEPT_PARAMS;
+
+typedef struct SYS_SHM_OPEN_PARAMS {
+ const char *name;
+ int oflag;
+ mode_t mode;
+} __attribute__((packed)) SYS_SHM_OPEN_PARAMS;
+
+typedef struct SYS_FTRUNCATE_PARAMS {
+ int fildes;
+ uint64_t length;
+} __attribute__((packed)) SYS_FTRUNCATE_PARAMS;
+
+typedef struct SYS_STAT_PARAMS {
+ const char *pathname;
+ struct stat *statbuf;
+} __attribute__((packed)) SYS_STAT_PARAMS;
+#endif
diff --git a/userland/libc/time.h b/userland/libc/time.h
new file mode 100644
index 0000000..771e430
--- /dev/null
+++ b/userland/libc/time.h
@@ -0,0 +1,20 @@
+#include <sys/types.h>
+
+struct tm {
+ int tm_sec;
+ int tm_min;
+ int tm_hour;
+ int tm_mday;
+ int tm_mon;
+ int tm_year;
+ int tm_wday;
+ int tm_yday;
+ int tm_isdst;
+ long __tm_gmtoff;
+ const char *__tm_zone;
+};
+
+struct timespec {
+ time_t tv_sec; // Seconds.
+ long tv_nsec; // Nanoseconds.
+};
diff --git a/userland/libc/time/clock_gettime.c b/userland/libc/time/clock_gettime.c
new file mode 100644
index 0000000..15f0cb7
--- /dev/null
+++ b/userland/libc/time/clock_gettime.c
@@ -0,0 +1,14 @@
+#include <syscall.h>
+#include <time.h>
+
+int clock_gettime(clockid_t clock_id, struct timespec *tp) {
+ tp->tv_sec = 0;
+ tp->tv_nsec = 0;
+ return 0;
+ /*
+SYS_CLOCK_GETTIME_PARAMS args = {
+.clk = clock_id,
+.ts = tp,
+};
+return syscall(SYS_CLOCK_GETTIME, &args);*/
+}
diff --git a/userland/libc/time/ctime_r.c b/userland/libc/time/ctime_r.c
new file mode 100644
index 0000000..66e6416
--- /dev/null
+++ b/userland/libc/time/ctime_r.c
@@ -0,0 +1,13 @@
+#include <string.h>
+#include <time.h>
+
+// TODO: Implement this
+
+// Time, formatting and parsing are some of the most annoying parts of
+// programming. Lets just hope this function is not important
+char *ctime_r(const time_t *clock, char *buf) {
+ (void)clock;
+ size_t l = strlen(buf);
+ memset(buf, '0', l);
+ return buf;
+}
diff --git a/userland/libc/time/gmtime.c b/userland/libc/time/gmtime.c
new file mode 100644
index 0000000..44e0ff3
--- /dev/null
+++ b/userland/libc/time/gmtime.c
@@ -0,0 +1,21 @@
+#include <time.h>
+
+struct tm gmtime_r = {
+ .tm_sec = 0,
+ .tm_min = 0,
+ .tm_hour = 0,
+ .tm_mday = 0,
+ .tm_mon = 0,
+ .tm_year = 0,
+ .tm_wday = 0,
+ .tm_yday = 0,
+ .tm_isdst = 0,
+ .__tm_gmtoff = 0,
+ .__tm_zone = 0,
+};
+
+// https://pubs.opengroup.org/onlinepubs/9699919799/functions/gmtime.html
+struct tm *gmtime(const time_t *timer) {
+ // TODO: Implement
+ return &gmtime_r;
+}
diff --git a/userland/libc/time/localtime.c b/userland/libc/time/localtime.c
new file mode 100644
index 0000000..40ca351
--- /dev/null
+++ b/userland/libc/time/localtime.c
@@ -0,0 +1,21 @@
+#include <time.h>
+
+ struct tm localtime_r = {
+ .tm_sec = 0,
+ .tm_min = 0,
+ .tm_hour = 0,
+ .tm_mday = 0,
+ .tm_mon = 0,
+ .tm_year = 0,
+ .tm_wday = 0,
+ .tm_yday = 0,
+ .tm_isdst = 0,
+ .__tm_gmtoff = 0,
+ .__tm_zone = 0,
+ };
+
+// https://pubs.opengroup.org/onlinepubs/9699919799/functions/localtime.html
+struct tm *localtime(const time_t *timer) {
+ // TODO: Implement
+ return &localtime_r;
+}
diff --git a/userland/libc/time/strftime.c b/userland/libc/time/strftime.c
new file mode 100644
index 0000000..30a080d
--- /dev/null
+++ b/userland/libc/time/strftime.c
@@ -0,0 +1,7 @@
+#include <time.h>
+#include <stddef.h>
+
+size_t strftime(char *restrict s, size_t maxsize,
+ const char *restrict format, const struct tm *restrict timeptr) {
+ return 0;
+}
diff --git a/userland/libc/time/time.c b/userland/libc/time/time.c
new file mode 100644
index 0000000..9931b71
--- /dev/null
+++ b/userland/libc/time/time.c
@@ -0,0 +1,9 @@
+#include <time.h>
+
+time_t time(time_t *tloc) {
+ struct timespec ts;
+ clock_gettime(CLOCK_REALTIME, &ts);
+ if (tloc)
+ *tloc = ts.tv_sec;
+ return ts.tv_sec;
+}
diff --git a/userland/libc/ubsan.c b/userland/libc/ubsan.c
new file mode 100644
index 0000000..9ac9879
--- /dev/null
+++ b/userland/libc/ubsan.c
@@ -0,0 +1,49 @@
+#include <stdio.h>
+#include <ubsan.h>
+
+void ubsan_log(const char *cause, struct source_location source) {
+ printf("UBSAN\n");
+ printf("%s: %s : %d\n", cause, source.file_name, source.line);
+ for (;;)
+ ;
+}
+
+void __ubsan_handle_shift_out_of_bounds(struct ShiftOutOfBoundsData *data,
+ unsigned long lhs, unsigned long rhs) {
+ (void)lhs;
+ (void)rhs;
+ ubsan_log("handle_shift_out_of_bounds", data->location);
+}
+
+void __ubsan_handle_add_overflow(struct OverflowData *data, unsigned long lhs,
+ unsigned long rhs) {
+ (void)lhs;
+ (void)rhs;
+ ubsan_log("handle_add_overflow", data->location);
+}
+
+void __ubsan_handle_sub_overflow(struct OverflowData *data, unsigned long lhs,
+ unsigned long rhs) {
+ (void)lhs;
+ (void)rhs;
+ ubsan_log("handle_sub_overflow", data->location);
+}
+
+void __ubsan_handle_negate_overflow(struct OverflowData *data, unsigned long lhs,
+ unsigned long rhs) {
+ (void)lhs;
+ (void)rhs;
+ ubsan_log("handle_negate_overflow", data->location);
+}
+
+void __ubsan_handle_mul_overflow(struct OverflowData *data, unsigned long lhs,
+ unsigned long rhs) {
+ (void)lhs;
+ (void)rhs;
+ ubsan_log("handle_mul_overflow", data->location);
+}
+
+void __ubsan_handle_out_of_bounds(struct OutOfBoundsData *data, void *index) {
+ (void)index;
+ ubsan_log("handle_out_of_bounds", data->location);
+}
diff --git a/userland/libc/ubsan.h b/userland/libc/ubsan.h
new file mode 100644
index 0000000..dac5407
--- /dev/null
+++ b/userland/libc/ubsan.h
@@ -0,0 +1,79 @@
+#include <stdint.h>
+
+enum { type_kind_int = 0, type_kind_float = 1, type_unknown = 0xffff };
+
+struct type_descriptor {
+ uint16_t type_kind;
+ uint16_t type_info;
+ char type_name[1];
+};
+
+struct source_location {
+ const char *file_name;
+ union {
+ unsigned long reported;
+ struct {
+ uint32_t line;
+ uint32_t column;
+ };
+ };
+};
+
+struct OverflowData {
+ struct source_location location;
+ struct type_descriptor *type;
+};
+
+struct type_mismatch_data {
+ struct source_location location;
+ struct type_descriptor *type;
+ unsigned long alignment;
+ unsigned char type_check_kind;
+};
+
+struct type_mismatch_data_v1 {
+ struct source_location location;
+ struct type_descriptor *type;
+ unsigned char log_alignment;
+ unsigned char type_check_kind;
+};
+
+struct type_mismatch_data_common {
+ struct source_location *location;
+ struct type_descriptor *type;
+ unsigned long alignment;
+ unsigned char type_check_kind;
+};
+
+struct nonnull_arg_data {
+ struct source_location location;
+ struct source_location attr_location;
+ int arg_index;
+};
+
+struct OutOfBoundsData {
+ struct source_location location;
+ struct type_descriptor *array_type;
+ struct type_descriptor *index_type;
+};
+
+struct ShiftOutOfBoundsData {
+ struct source_location location;
+ struct type_descriptor *lhs_type;
+ struct type_descriptor *rhs_type;
+};
+
+struct unreachable_data {
+ struct source_location location;
+};
+
+struct invalid_value_data {
+ struct source_location location;
+ struct type_descriptor *type;
+};
+
+struct alignment_assumption_data {
+ struct source_location location;
+ struct source_location assumption_location;
+ struct type_descriptor *type;
+};
diff --git a/userland/libc/unistd.h b/userland/libc/unistd.h
new file mode 100644
index 0000000..b1e3434
--- /dev/null
+++ b/userland/libc/unistd.h
@@ -0,0 +1,14 @@
+#ifndef UNISTD_H
+#define UNISTD_H
+#include <stddef.h>
+
+extern int opterr, optind, optopt;
+extern char *optarg;
+
+int close(int fildes);
+int ftruncate(int fildes, size_t length);
+int execv(char *path, char **argv);
+int pipe(int fd[2]);
+int dup2(int org_fd, int new_fd);
+int getopt(int argc, char * const argv[], const char *optstring);
+#endif
diff --git a/userland/libc/unistd/_exit.c b/userland/libc/unistd/_exit.c
new file mode 100644
index 0000000..c6d64be
--- /dev/null
+++ b/userland/libc/unistd/_exit.c
@@ -0,0 +1,8 @@
+#include <syscall.h>
+#include <unistd.h>
+
+// FIXME: Technically exit and _exit are different but this
+// stackoverflow answer says that it does not usually matter. So lets
+// hope that is the case.
+// https://stackoverflow.com/a/5423108
+void _exit(int status) { syscall(SYS_EXIT, (void *)status, 0, 0, 0, 0); }
diff --git a/userland/libc/unistd/execvp.c b/userland/libc/unistd/execvp.c
new file mode 100644
index 0000000..573e822
--- /dev/null
+++ b/userland/libc/unistd/execvp.c
@@ -0,0 +1,8 @@
+#include <unistd.h>
+#include <syscall.h>
+
+// FIXME: Path resolution
+int execvp(const char *file, char *const argv[]) {
+ struct SYS_EXEC_PARAMS args = {.path = file, .argv = argv};
+ return syscall(SYS_EXEC, &args, 0, 0, 0, 0);
+}
diff --git a/userland/libc/unistd/getopt.c b/userland/libc/unistd/getopt.c
new file mode 100644
index 0000000..a026b59
--- /dev/null
+++ b/userland/libc/unistd/getopt.c
@@ -0,0 +1,14 @@
+#include <assert.h>
+#include <unistd.h>
+
+int opterr, optind, optopt;
+char *optarg;
+
+// https://pubs.opengroup.org/onlinepubs/9699919799/functions/getopt.html
+int getopt(int argc, char *const argv[], const char *optstring) {
+ // TODO
+ optind = 1;
+ optarg = NULL;
+ // assert(0);
+ return -1;
+}
diff --git a/userland/libc/unistd/getpid.c b/userland/libc/unistd/getpid.c
new file mode 100644
index 0000000..8aeef10
--- /dev/null
+++ b/userland/libc/unistd/getpid.c
@@ -0,0 +1,7 @@
+#include <unistd.h>
+#include <syscall.h>
+#include <sys/types.h>
+
+pid_t getpid(void) {
+ return s_syscall(SYS_GETPID);
+}
diff --git a/userland/libc/unistd/msleep.c b/userland/libc/unistd/msleep.c
new file mode 100644
index 0000000..0b016c6
--- /dev/null
+++ b/userland/libc/unistd/msleep.c
@@ -0,0 +1,6 @@
+// Not standard, but it feels like it should be.
+#include <syscall.h>
+#include <unistd.h>
+#include <stdint.h>
+
+void msleep(uint32_t ms) { syscall(SYS_MSLEEP, (void *)ms, 0, 0, 0, 0); }
diff --git a/userland/libc/unistd/unlink.c b/userland/libc/unistd/unlink.c
new file mode 100644
index 0000000..ccac0df
--- /dev/null
+++ b/userland/libc/unistd/unlink.c
@@ -0,0 +1,7 @@
+#include <unistd.h>
+
+int unlink(const char *path) {
+ // TODO
+ printf("TODO: Implement unlink");
+ return 0;
+}
diff --git a/userland/libc/unistd/uptime.c b/userland/libc/unistd/uptime.c
new file mode 100644
index 0000000..090a0e5
--- /dev/null
+++ b/userland/libc/unistd/uptime.c
@@ -0,0 +1,6 @@
+// Not standard, but it feels like it should be.
+#include <stdint.h>
+#include <syscall.h>
+#include <unistd.h>
+
+uint32_t uptime(void) { return syscall(SYS_UPTIME, 0, 0, 0, 0, 0); }
diff --git a/userland/libc/wchar.h b/userland/libc/wchar.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/userland/libc/wchar.h
diff --git a/userland/libc/wctype.h b/userland/libc/wctype.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/userland/libc/wctype.h
diff --git a/userland/libgui/Makefile b/userland/libgui/Makefile
new file mode 100644
index 0000000..5a895c4
--- /dev/null
+++ b/userland/libgui/Makefile
@@ -0,0 +1,17 @@
+CC="/home/anton/prj/osdev/sysroot/bin/i686-sb-gcc"
+AR="/home/anton/prj/osdev/sysroot/bin/i686-sb-ar"
+#CFLAGS = -ggdb -ffreestanding -O0 -Wall -Wextra -pedantic -mgeneral-regs-only -Wimplicit-fallthrough -nostdlib -static -Wno-undef -fsanitize=shift,signed-integer-overflow,bounds
+CFLAGS = -O2 -ggdb -ffreestanding -O0 -Wall -Wextra -pedantic -mgeneral-regs-only -Wimplicit-fallthrough -nostdlib -static -Wno-undef
+BINS=libgui.a
+all: $(BINS)
+LIBS=-L../libc -lc -L../json -ljson -lgcc
+OBJ=libgui.o
+
+libgui.o: libgui.c
+ $(CC) $(CFLAGS) -c libgui.c -I../libc/ -I../json/ $(LIBS)
+
+libgui.a: $(OBJ)
+ $(AR) rcs libgui.a $^
+
+clean:
+ rm $(OBJ) $(BINS)
diff --git a/userland/libgui/font.h b/userland/libgui/font.h
new file mode 100644
index 0000000..763b438
--- /dev/null
+++ b/userland/libgui/font.h
@@ -0,0 +1,3 @@
+#ifndef FONT_H
+#define FONT_H
+#endif
diff --git a/userland/libgui/libgui.c b/userland/libgui/libgui.c
new file mode 100644
index 0000000..5f5526d
--- /dev/null
+++ b/userland/libgui/libgui.c
@@ -0,0 +1,290 @@
+#include "libgui.h"
+#include "font.h"
+#include <assert.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
+#define place_pixel_pos(_p, _pos) \
+ { *(uint32_t *)(w->bitmap_ptr + _pos) = _p; }
+
+static const unsigned char font8x8_basic[128][8] = {
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0000 (nul)
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0001
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0002
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0003
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0004
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0005
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0006
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0007
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0008
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0009
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000A
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000B
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000C
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000D
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000E
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000F
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0010
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0011
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0012
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0013
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0014
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0015
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0016
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0017
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0018
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0019
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001A
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001B
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001C
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001D
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001E
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001F
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0020 (space)
+ {0x18, 0x3C, 0x3C, 0x18, 0x18, 0x00, 0x18, 0x00}, // U+0021 (!)
+ {0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0022 (")
+ {0x36, 0x36, 0x7F, 0x36, 0x7F, 0x36, 0x36, 0x00}, // U+0023 (#)
+ {0x0C, 0x3E, 0x03, 0x1E, 0x30, 0x1F, 0x0C, 0x00}, // U+0024 ($)
+ {0x00, 0x63, 0x33, 0x18, 0x0C, 0x66, 0x63, 0x00}, // U+0025 (%)
+ {0x1C, 0x36, 0x1C, 0x6E, 0x3B, 0x33, 0x6E, 0x00}, // U+0026 (&)
+ {0x06, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0027 (')
+ {0x18, 0x0C, 0x06, 0x06, 0x06, 0x0C, 0x18, 0x00}, // U+0028 (()
+ {0x06, 0x0C, 0x18, 0x18, 0x18, 0x0C, 0x06, 0x00}, // U+0029 ())
+ {0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00}, // U+002A (*)
+ {0x00, 0x0C, 0x0C, 0x3F, 0x0C, 0x0C, 0x00, 0x00}, // U+002B (+)
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x06}, // U+002C (,)
+ {0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00}, // U+002D (-)
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x00}, // U+002E (.)
+ {0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x00}, // U+002F (/)
+ {0x3E, 0x63, 0x73, 0x7B, 0x6F, 0x67, 0x3E, 0x00}, // U+0030 (0)
+ {0x0C, 0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x3F, 0x00}, // U+0031 (1)
+ {0x1E, 0x33, 0x30, 0x1C, 0x06, 0x33, 0x3F, 0x00}, // U+0032 (2)
+ {0x1E, 0x33, 0x30, 0x1C, 0x30, 0x33, 0x1E, 0x00}, // U+0033 (3)
+ {0x38, 0x3C, 0x36, 0x33, 0x7F, 0x30, 0x78, 0x00}, // U+0034 (4)
+ {0x3F, 0x03, 0x1F, 0x30, 0x30, 0x33, 0x1E, 0x00}, // U+0035 (5)
+ {0x1C, 0x06, 0x03, 0x1F, 0x33, 0x33, 0x1E, 0x00}, // U+0036 (6)
+ {0x3F, 0x33, 0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x00}, // U+0037 (7)
+ {0x1E, 0x33, 0x33, 0x1E, 0x33, 0x33, 0x1E, 0x00}, // U+0038 (8)
+ {0x1E, 0x33, 0x33, 0x3E, 0x30, 0x18, 0x0E, 0x00}, // U+0039 (9)
+ {0x00, 0x0C, 0x0C, 0x00, 0x00, 0x0C, 0x0C, 0x00}, // U+003A (:)
+ {0x00, 0x0C, 0x0C, 0x00, 0x00, 0x0C, 0x0C, 0x06}, // U+003B (;)
+ {0x18, 0x0C, 0x06, 0x03, 0x06, 0x0C, 0x18, 0x00}, // U+003C (<)
+ {0x00, 0x00, 0x3F, 0x00, 0x00, 0x3F, 0x00, 0x00}, // U+003D (=)
+ {0x06, 0x0C, 0x18, 0x30, 0x18, 0x0C, 0x06, 0x00}, // U+003E (>)
+ {0x1E, 0x33, 0x30, 0x18, 0x0C, 0x00, 0x0C, 0x00}, // U+003F (?)
+ {0x3E, 0x63, 0x7B, 0x7B, 0x7B, 0x03, 0x1E, 0x00}, // U+0040 (@)
+ {0x0C, 0x1E, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x00}, // U+0041 (A)
+ {0x3F, 0x66, 0x66, 0x3E, 0x66, 0x66, 0x3F, 0x00}, // U+0042 (B)
+ {0x3C, 0x66, 0x03, 0x03, 0x03, 0x66, 0x3C, 0x00}, // U+0043 (C)
+ {0x1F, 0x36, 0x66, 0x66, 0x66, 0x36, 0x1F, 0x00}, // U+0044 (D)
+ {0x7F, 0x46, 0x16, 0x1E, 0x16, 0x46, 0x7F, 0x00}, // U+0045 (E)
+ {0x7F, 0x46, 0x16, 0x1E, 0x16, 0x06, 0x0F, 0x00}, // U+0046 (F)
+ {0x3C, 0x66, 0x03, 0x03, 0x73, 0x66, 0x7C, 0x00}, // U+0047 (G)
+ {0x33, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x33, 0x00}, // U+0048 (H)
+ {0x1E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+0049 (I)
+ {0x78, 0x30, 0x30, 0x30, 0x33, 0x33, 0x1E, 0x00}, // U+004A (J)
+ {0x67, 0x66, 0x36, 0x1E, 0x36, 0x66, 0x67, 0x00}, // U+004B (K)
+ {0x0F, 0x06, 0x06, 0x06, 0x46, 0x66, 0x7F, 0x00}, // U+004C (L)
+ {0x63, 0x77, 0x7F, 0x7F, 0x6B, 0x63, 0x63, 0x00}, // U+004D (M)
+ {0x63, 0x67, 0x6F, 0x7B, 0x73, 0x63, 0x63, 0x00}, // U+004E (N)
+ {0x1C, 0x36, 0x63, 0x63, 0x63, 0x36, 0x1C, 0x00}, // U+004F (O)
+ {0x3F, 0x66, 0x66, 0x3E, 0x06, 0x06, 0x0F, 0x00}, // U+0050 (P)
+ {0x1E, 0x33, 0x33, 0x33, 0x3B, 0x1E, 0x38, 0x00}, // U+0051 (Q)
+ {0x3F, 0x66, 0x66, 0x3E, 0x36, 0x66, 0x67, 0x00}, // U+0052 (R)
+ {0x1E, 0x33, 0x07, 0x0E, 0x38, 0x33, 0x1E, 0x00}, // U+0053 (S)
+ {0x3F, 0x2D, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+0054 (T)
+ {0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x3F, 0x00}, // U+0055 (U)
+ {0x33, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x00}, // U+0056 (V)
+ {0x63, 0x63, 0x63, 0x6B, 0x7F, 0x77, 0x63, 0x00}, // U+0057 (W)
+ {0x63, 0x63, 0x36, 0x1C, 0x1C, 0x36, 0x63, 0x00}, // U+0058 (X)
+ {0x33, 0x33, 0x33, 0x1E, 0x0C, 0x0C, 0x1E, 0x00}, // U+0059 (Y)
+ {0x7F, 0x63, 0x31, 0x18, 0x4C, 0x66, 0x7F, 0x00}, // U+005A (Z)
+ {0x1E, 0x06, 0x06, 0x06, 0x06, 0x06, 0x1E, 0x00}, // U+005B ([)
+ {0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x40, 0x00}, // U+005C (\)
+ {0x1E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1E, 0x00}, // U+005D (])
+ {0x08, 0x1C, 0x36, 0x63, 0x00, 0x00, 0x00, 0x00}, // U+005E (^)
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF}, // U+005F (_)
+ {0x0C, 0x0C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0060 (`)
+ {0x00, 0x00, 0x1E, 0x30, 0x3E, 0x33, 0x6E, 0x00}, // U+0061 (a)
+ {0x07, 0x06, 0x06, 0x3E, 0x66, 0x66, 0x3B, 0x00}, // U+0062 (b)
+ {0x00, 0x00, 0x1E, 0x33, 0x03, 0x33, 0x1E, 0x00}, // U+0063 (c)
+ {0x38, 0x30, 0x30, 0x3e, 0x33, 0x33, 0x6E, 0x00}, // U+0064 (d)
+ {0x00, 0x00, 0x1E, 0x33, 0x3f, 0x03, 0x1E, 0x00}, // U+0065 (e)
+ {0x1C, 0x36, 0x06, 0x0f, 0x06, 0x06, 0x0F, 0x00}, // U+0066 (f)
+ {0x00, 0x00, 0x6E, 0x33, 0x33, 0x3E, 0x30, 0x1F}, // U+0067 (g)
+ {0x07, 0x06, 0x36, 0x6E, 0x66, 0x66, 0x67, 0x00}, // U+0068 (h)
+ {0x0C, 0x00, 0x0E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+0069 (i)
+ {0x30, 0x00, 0x30, 0x30, 0x30, 0x33, 0x33, 0x1E}, // U+006A (j)
+ {0x07, 0x06, 0x66, 0x36, 0x1E, 0x36, 0x67, 0x00}, // U+006B (k)
+ {0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+006C (l)
+ {0x00, 0x00, 0x33, 0x7F, 0x7F, 0x6B, 0x63, 0x00}, // U+006D (m)
+ {0x00, 0x00, 0x1F, 0x33, 0x33, 0x33, 0x33, 0x00}, // U+006E (n)
+ {0x00, 0x00, 0x1E, 0x33, 0x33, 0x33, 0x1E, 0x00}, // U+006F (o)
+ {0x00, 0x00, 0x3B, 0x66, 0x66, 0x3E, 0x06, 0x0F}, // U+0070 (p)
+ {0x00, 0x00, 0x6E, 0x33, 0x33, 0x3E, 0x30, 0x78}, // U+0071 (q)
+ {0x00, 0x00, 0x3B, 0x6E, 0x66, 0x06, 0x0F, 0x00}, // U+0072 (r)
+ {0x00, 0x00, 0x3E, 0x03, 0x1E, 0x30, 0x1F, 0x00}, // U+0073 (s)
+ {0x08, 0x0C, 0x3E, 0x0C, 0x0C, 0x2C, 0x18, 0x00}, // U+0074 (t)
+ {0x00, 0x00, 0x33, 0x33, 0x33, 0x33, 0x6E, 0x00}, // U+0075 (u)
+ {0x00, 0x00, 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x00}, // U+0076 (v)
+ {0x00, 0x00, 0x63, 0x6B, 0x7F, 0x7F, 0x36, 0x00}, // U+0077 (w)
+ {0x00, 0x00, 0x63, 0x36, 0x1C, 0x36, 0x63, 0x00}, // U+0078 (x)
+ {0x00, 0x00, 0x33, 0x33, 0x33, 0x3E, 0x30, 0x1F}, // U+0079 (y)
+ {0x00, 0x00, 0x3F, 0x19, 0x0C, 0x26, 0x3F, 0x00}, // U+007A (z)
+ {0x38, 0x0C, 0x0C, 0x07, 0x0C, 0x0C, 0x38, 0x00}, // U+007B ({)
+ {0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00}, // U+007C (|)
+ {0x07, 0x0C, 0x0C, 0x38, 0x0C, 0x0C, 0x07, 0x00}, // U+007D (})
+ {0x6E, 0x3B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+007E (~)
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} // U+007F
+};
+
+#define pokeb(S, O, V) (*(unsigned char *)((S) + (O)) = (V))
+
+// Very temporary
+char *random_string(void) {
+ int fd = open("/dev/urandom", O_RDONLY, 0);
+ char *r = malloc(sizeof(char[10]));
+ for (int i = 0; i < 10 - 1; i++) {
+ char c;
+ read(fd, &c, 1);
+ r[i] = 'a' + (c & 0xF);
+ }
+ close(fd);
+ r[9] = '\0';
+ printf("r: %s\n", r);
+ return r;
+}
+
+int get_bitmap_value(const unsigned char bitmap[], int i) {
+ int array_index = i / 8;
+ int byte_index = i % 8;
+ int rc = (bitmap[array_index] >> byte_index) & 0x1;
+ return rc;
+}
+
+void GUI_OverwriteFont(GUI_Window *w, uint32_t px, uint32_t py,
+ const uint32_t color) {
+ int sx, sy;
+ sx = 8;
+ sy = 8;
+ int x, y;
+ x = px;
+ y = py;
+ if (px + sx > w->sx)
+ return;
+ if (py + sy > w->sy)
+ return;
+ for (int i = 0; i < sx * sy; i++) {
+ int pos = x + y * w->sx;
+ place_pixel_pos(color, pos);
+ x++;
+ if (x >= sx + px) {
+ y++;
+ x = px;
+ }
+ if (y > py + sy)
+ break;
+ }
+}
+
+void GUI_DrawFont(GUI_Window *w, uint32_t px, uint32_t py, const uint32_t c) {
+ int sx, sy;
+ sx = 8;
+ sy = 8;
+ int x, y;
+ x = px;
+ y = py;
+ if (px + sx > w->sx)
+ return;
+ if (py + sy > w->sy)
+ return;
+ const unsigned char *bitmap = font8x8_basic[c];
+ for (int i = 0; i < sx * sy; i++) {
+ int pos = x + y * w->sx;
+ if (get_bitmap_value(bitmap, i)) {
+ place_pixel_pos(0xFFFFFF, pos);
+ } else {
+ place_pixel_pos(0x0, pos);
+ }
+ x++;
+ if (x >= sx + px) {
+ y++;
+ x = px;
+ }
+ if (y > py + sy)
+ break;
+ }
+}
+
+typedef struct {
+ uint16_t px;
+ uint16_t py;
+ uint16_t sx;
+ uint16_t sy;
+ uint8_t name_len;
+} WS_EVENT_CREATE;
+
+void GUI_ClearScreen(GUI_Window *w, uint32_t color) {
+ for (int i = 0; i < w->sx * w->sy; i++)
+ w->bitmap_ptr[i] =color;
+}
+
+GUI_Window *GUI_CreateWindow(uint32_t x, uint32_t y, uint32_t sx, uint32_t sy) {
+ GUI_Window *w = malloc(sizeof(GUI_Window));
+ if (!w)
+ return NULL;
+ w->x = x;
+ w->y = y;
+ w->sx = sx;
+ w->sy = sy;
+
+ // Connect to the windowserver
+ int ws_fd = -1;
+ for (; - 1 == ws_fd;) {
+ ws_fd = open("/dev/windowserver", O_RDWR | O_NONBLOCK, 0);
+ }
+ w->ws_socket = ws_fd;
+ char *str = random_string();
+ WS_EVENT_CREATE e;
+ e.px = x;
+ e.py = y;
+ e.sx = sx;
+ e.sy = sy;
+ e.name_len = (uint8_t)strlen(str) + 1;
+
+ // Create bitmap
+ w->bitmap_fd = shm_open(str, O_RDWR, 0);
+ if (!((int)w->bitmap_fd >= 0)) {
+ printf("bitmap_fd: %x\n", w->bitmap_fd);
+ assert(0);
+ }
+ ftruncate(w->bitmap_fd, sx * sy * sizeof(uint32_t));
+ void *rc = mmap(NULL, sx * sy * sizeof(uint32_t), 0, 0, w->bitmap_fd, 0);
+ if (!((int)rc >= 0)) {
+ printf("rc: %x\n", rc);
+ assert(0);
+ }
+ w->bitmap_ptr = rc;
+
+ // Send the request to the windowserver
+ uint8_t l = 1;
+ uint8_t len = sizeof(l) + sizeof(e) + e.name_len;
+ char *buffer = malloc(len);
+ char *p = buffer;
+ memcpy(p, &l, sizeof(l));
+ p += sizeof(l);
+ memcpy(p, &e, sizeof(e));
+ p += sizeof(e);
+ strcpy(p, str);
+ write(ws_fd, buffer, len);
+ return w;
+}
+
+void GUI_UpdateWindow(GUI_Window *w) {
+ uint8_t l = 0;
+ write(w->ws_socket, &l, sizeof(l));
+}
diff --git a/userland/libgui/libgui.h b/userland/libgui/libgui.h
new file mode 100644
index 0000000..d58c23c
--- /dev/null
+++ b/userland/libgui/libgui.h
@@ -0,0 +1,34 @@
+#ifndef LIBGUI_H
+#define LIBGUI_H
+#include <stddef.h>
+#include <stdint.h>
+
+typedef struct {
+ int ws_socket;
+ int bitmap_fd;
+ uint32_t *bitmap_ptr;
+ int x;
+ int y;
+ int sx;
+ int sy;
+} GUI_Window;
+
+// Taken from drivers/keyboard.c
+struct KEY_EVENT {
+ char c;
+ uint8_t mode; // (shift (0 bit)) (alt (1 bit))
+ uint8_t release; // 0 pressed, 1 released
+};
+
+typedef struct {
+ int type;
+ struct KEY_EVENT ev;
+} WS_EVENT;
+
+GUI_Window *GUI_CreateWindow(uint32_t x, uint32_t y, uint32_t sx, uint32_t sy);
+void GUI_DrawFont(GUI_Window *w, uint32_t px, uint32_t py, const uint32_t c);
+void GUI_UpdateWindow(GUI_Window *w);
+void GUI_OverwriteFont(GUI_Window *w, uint32_t px, uint32_t py,
+ const uint32_t color);
+void GUI_ClearScreen(GUI_Window *w, uint32_t color);
+#endif
diff --git a/userland/minibox/Makefile b/userland/minibox/Makefile
new file mode 100644
index 0000000..5448f96
--- /dev/null
+++ b/userland/minibox/Makefile
@@ -0,0 +1,12 @@
+CC="/home/anton/prj/osdev/sysroot/bin/i686-sb-gcc"
+CFLAGS=-Wall -Wextra -pedantic -Wimplicit-fallthrough -g -O0
+OBJ=minibox.o utilities/cat.o utilities/echo.o utilities/yes.o utilities/minibox.o utilities/ascii.o utilities/wc.o utilities/init.o utilities/ls.o utilities/touch.o utilities/ed.o
+
+%.o: %.c
+ $(CC) $(CFLAGS) $(INCLUDE) $(LIBS) -c $< -o $@
+
+minibox: $(OBJ)
+ $(CC) $(INCLUDE) -o $@ $^ $(CFLAGS) $(LIBS)
+
+clean:
+ rm minibox $(OBJ)
diff --git a/userland/minibox/minibox.c b/userland/minibox/minibox.c
new file mode 100644
index 0000000..63eaee8
--- /dev/null
+++ b/userland/minibox/minibox.c
@@ -0,0 +1,65 @@
+// SPDX-License-Identifier: 0BSD
+// TODO: Possibly use getprogname() instead of using argv[0] to get the
+// utility name.
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "utilities/include.h"
+
+#define ARRAY_LENGTH(array) (sizeof(array) / sizeof((array)[0]))
+
+typedef struct Command {
+ char *name;
+ int (*function)(int, char **);
+} Command;
+
+#define STR2(_x) #_x
+#define STR(_x) STR2(_x)
+#define COMMAND(NAME) \
+ { STR(NAME), NAME##_main }
+
+Command utilities[] = {COMMAND(minibox), COMMAND(ascii), COMMAND(echo),
+ COMMAND(cat), COMMAND(yes), COMMAND(wc),
+ COMMAND(init), COMMAND(ls), COMMAND(touch),
+ COMMAND(ed)};
+
+char *parse_filename(char *str) {
+ char *tmp = NULL, *is = str;
+ for (; *is++;)
+ if ('/' == *is)
+ tmp = is;
+ return tmp ? tmp + 1 : str;
+}
+
+void usage(void) {
+ for (int i = 0; i < ARRAY_LENGTH(utilities); i++) {
+ printf("%s ", utilities[i].name);
+ }
+ printf("\n");
+}
+
+int main(int argc, char **argv) {
+ if (argc < 1)
+ return 1;
+#ifdef SINGLE_MAIN
+ return utilities[0].function(argc, argv);
+#endif
+
+ // argv[0] will be checked to determine what utility
+ // is supposed to be ran.
+ // NOTE: "minibox" is a utility than can be ran. "minibox"
+ // will switch argv and argc so that argv[1] -> argv[0]
+ // then it will rerun main(). This allows utlities
+ // to be ran like "minibox <utility> <arguments>" or
+ // even "minibox minibox <utility> <arguments>"
+ const char *utility_name = parse_filename(argv[0]);
+ if (*utility_name == '/')
+ utility_name++;
+ for (int i = 0; i < ARRAY_LENGTH(utilities); i++)
+ if (0 == strcmp(utility_name, utilities[i].name))
+ return utilities[i].function(argc, argv);
+
+ usage();
+ return 0;
+}
diff --git a/userland/minibox/utilities/ascii.c b/userland/minibox/utilities/ascii.c
new file mode 100644
index 0000000..53429dc
--- /dev/null
+++ b/userland/minibox/utilities/ascii.c
@@ -0,0 +1,30 @@
+#include <stdio.h>
+
+const char * const ascii_table[] =
+{
+"Dec Hex Dec Hex Dec Hex Dec Hex Dec Hex Dec Hex Dec Hex Dec Hex",
+" 0 00 NUL 16 10 DLE 32 20 48 30 0 64 40 @ 80 50 P 96 60 ` 112 70 p",
+" 1 01 SOH 17 11 DC1 33 21 ! 49 31 1 65 41 A 81 51 Q 97 61 a 113 71 q",
+" 2 02 STX 18 12 DC2 34 22 \" 50 32 2 66 42 B 82 52 R 98 62 b 114 72 r",
+" 3 03 ETX 19 13 DC3 35 23 # 51 33 3 67 43 C 83 53 S 99 63 c 115 73 s",
+" 4 04 EOT 20 14 DC4 36 24 $ 52 34 4 68 44 D 84 54 T 100 64 d 116 74 t",
+" 5 05 ENQ 21 15 NAK 37 25 % 53 35 5 69 45 E 85 55 U 101 65 e 117 75 u",
+" 6 06 ACK 22 16 SYN 38 26 & 54 36 6 70 46 F 86 56 V 102 66 f 118 76 v",
+" 7 07 BEL 23 17 ETB 39 27 ' 55 37 7 71 47 G 87 57 W 103 67 g 119 77 w",
+" 8 08 BS 24 18 CAN 40 28 ( 56 38 8 72 48 H 88 58 X 104 68 h 120 78 x",
+" 9 09 HT 25 19 EM 41 29 ) 57 39 9 73 49 I 89 59 Y 105 69 i 121 79 y",
+" 10 0A LF 26 1A SUB 42 2A * 58 3A : 74 4A J 90 5A Z 106 6A j 122 7A z",
+" 11 0B VT 27 1B ESC 43 2B + 59 3B ; 75 4B K 91 5B [ 107 6B k 123 7B {",
+" 12 0C FF 28 1C FS 44 2C , 60 3C < 76 4C L 92 5C \\ 108 6C l 124 7C |",
+" 13 0D CR 29 1D GS 45 2D - 61 3D = 77 4D M 93 5D ] 109 6D m 125 7D }",
+" 14 0E SO 30 1E RS 46 2E . 62 3E > 78 4E N 94 5E ^ 110 6E n 126 7E ~",
+" 15 0F SI 31 1F US 47 2F / 63 3F ? 79 4F O 95 5F _ 111 6F o 127 7F DEL",
+};
+
+int ascii_main(int argc, char ** argv)
+{
+ for(int i = 0;i < sizeof(ascii_table)/sizeof(ascii_table[0]);i++)
+ puts(ascii_table[i]);
+
+ return 0;
+}
diff --git a/userland/minibox/utilities/cat.c b/userland/minibox/utilities/cat.c
new file mode 100644
index 0000000..c528d49
--- /dev/null
+++ b/userland/minibox/utilities/cat.c
@@ -0,0 +1,54 @@
+// cat - concatenate and print files
+// https://pubs.opengroup.org/onlinepubs/9699919799/
+//
+// TODO: Add -u flag "Write bytes from the input file to the standard
+// output without delay as each is read."
+#include "include.h"
+#include <dirent.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+int fd_to_stdout(int fd) {
+ int rc;
+ for (char buffer[CAT_BUFFER]; (rc = read(fd, &buffer, sizeof(buffer)));) {
+ if (-1 == rc)
+ return 0;
+ if (-1 == write(fd_stdout, buffer, rc))
+ return 0;
+ }
+ return 1;
+}
+
+int cat_main(int argc, char **argv) {
+ int fd = fd_stdin;
+
+ // If no file operands are specified, the standard input shall be
+ // used.
+ if (argc < 2) {
+ return (fd_to_stdout(0)) ? 0 : 1;
+ }
+
+ argv++;
+ for (; *argv; argv++) {
+ // If a file is '-', the cat utility shall read from the standard
+ // input at that point in the sequence.
+ if (0 == strcmp(*argv, "-")) {
+ if (!fd_to_stdout(0))
+ return 1;
+ continue;
+ }
+
+ if (-1 == (fd = open(*argv, O_RDONLY, 0))) {
+ printf("cat: ");
+ // fflush(stdout);
+ perror(*argv);
+ return 1;
+ }
+ if (!fd_to_stdout(fd))
+ return 1;
+ close(fd);
+ }
+ return 0;
+}
diff --git a/userland/minibox/utilities/echo.c b/userland/minibox/utilities/echo.c
new file mode 100644
index 0000000..5ec68a7
--- /dev/null
+++ b/userland/minibox/utilities/echo.c
@@ -0,0 +1,30 @@
+#include "include.h"
+#include <fcntl.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <unistd.h>
+
+int echo(char **str, int new_line) {
+ for (; *str;) {
+ printf("%s", *str);
+ if (*++str)
+ putchar(' ');
+ }
+
+ if (new_line)
+ putchar('\n');
+ return 0;
+}
+
+int echo_main(int argc, char **argv) {
+ int new_line = 1;
+
+ for (; *++argv && '-' == **argv;)
+ switch (*(*argv + 1)) {
+ case 'n':
+ new_line = 0;
+ break;
+ }
+
+ return echo(argv, new_line);
+}
diff --git a/userland/minibox/utilities/ed.c b/userland/minibox/utilities/ed.c
new file mode 100644
index 0000000..53270dc
--- /dev/null
+++ b/userland/minibox/utilities/ed.c
@@ -0,0 +1,145 @@
+// ed - edit text
+// ed [-p string] [-s] [file]
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#define COMMAND_MODE 0
+#define INPUT_MODE 1
+
+int mode = COMMAND_MODE;
+
+FILE *fp = NULL;
+FILE *mem_fp = NULL;
+int line_number = 1;
+
+int getline(char *buffer, size_t s) {
+ (void)s;
+ int i = 0;
+ char c;
+ for (;; i++) {
+ int rc = read(0, &c, 1);
+ assert(rc > 0);
+ printf("%c", c);
+ buffer[i] = c;
+ if ('\n' == c)
+ break;
+ }
+ buffer[i] = '\0';
+ return i;
+}
+
+void goto_line(void) {
+ char c;
+ fseek(mem_fp, 0, SEEK_SET);
+ int line = 1;
+ if (1 != line_number) {
+ // Goto line
+ for (; fread(&c, 1, 1, mem_fp);) {
+ if ('\n' == c)
+ line++;
+ if (line == line_number)
+ return;
+ }
+ printf("got to line: %d\n", line);
+ assert(0);
+ }
+}
+
+void read_line(void) {
+ char c;
+ goto_line();
+ for (; fread(&c, 1, 1, mem_fp);) {
+ if ('\n' == c)
+ break;
+ printf("%c", c);
+ }
+ printf("\n");
+}
+
+void goto_end_of_line(void) {
+ char c;
+ for (; fread(&c, 1, 1, mem_fp);) {
+ if ('\n' == c)
+ break;
+ }
+}
+
+void delete_line(void) {
+ long s = ftell(mem_fp);
+ printf("s: %d\n", s);
+ goto_end_of_line();
+ long end = ftell(mem_fp);
+ printf("end: %d\n", end);
+ long offset = end - s;
+ for (char buffer[4096];;) {
+ int rc = fread(buffer, 1, 100, mem_fp);
+ long reset = ftell(mem_fp);
+ if (0 == rc)
+ break;
+ fseek(mem_fp, s, SEEK_SET);
+ fwrite(buffer, 1, rc, mem_fp);
+ s += rc;
+ fseek(mem_fp, reset, SEEK_SET);
+ }
+}
+
+void read_command(void) {
+ char buffer[4096];
+ char *s = buffer;
+ getline(buffer, 4096);
+ int a = -1;
+ int rc = sscanf(buffer, "%d", &a);
+ if (0 < rc) {
+ line_number = a;
+ }
+ for (; isdigit(*s); s++)
+ ;
+ if (0 == strcmp(s, "i")) {
+ mode = INPUT_MODE;
+ return;
+ }
+ if (0 == strcmp(s, ".")) {
+ read_line();
+ return;
+ }
+ return;
+}
+
+void read_input(void) {
+ char buffer[4096];
+ int l = getline(buffer, 4096);
+ if (0 == strcmp(buffer, ".")) {
+ mode = COMMAND_MODE;
+ return;
+ }
+ goto_line();
+ delete_line();
+ goto_line();
+ assert(fwrite(buffer, l, 1, mem_fp));
+ return;
+}
+
+int ed_main(char argc, char **argv) {
+ if (argc < 2)
+ return 1;
+ char *buffer;
+ size_t size;
+ mem_fp = open_memstream(&buffer, &size);
+ assert(mem_fp);
+ fp = fopen(argv[1], "r");
+ assert(fp);
+ char r_buffer[4096];
+ for (int rc; (rc = fread(buffer, 1, 4096, fp));) {
+ fwrite(r_buffer, 1, rc, mem_fp);
+ }
+
+ for (;;) {
+ if (COMMAND_MODE == mode)
+ read_command();
+ else
+ read_input();
+ }
+ fclose(fp);
+ fclose(mem_fp);
+ return 0;
+}
diff --git a/userland/minibox/utilities/include.h b/userland/minibox/utilities/include.h
new file mode 100644
index 0000000..7ffd136
--- /dev/null
+++ b/userland/minibox/utilities/include.h
@@ -0,0 +1,41 @@
+#include <stdio.h>
+/* General constants */
+#define fd_stdin 0 /* standard in file descriptor */
+#define fd_stdout 1 /* standard out file descriptor */
+#define ASSERT_NOT_REACHED assert(0);
+/* END General constants */
+
+/* CAT SETTINGS */
+#define CAT_BUFFER 4096 /* size of the read buffer */
+/* END CAT SETTINGS */
+
+/* HTTP SETTINGS */
+#define HTTP_MAX_BUFFER 4096 /* size of the read buffer */
+#define HTTP_DEFAULT_PORT 1337 /* default port should -p not be supplied */
+#define HTTP_WEBSITE_ROOT "site/" /* default directory that it chroots into */
+
+/* should xxx.html not exist these will be supplied instead */
+#define HTTP_DEFAULT_404_SITE "404 - Not Found"
+#define HTTP_DEFAULT_400_SITE "400 - Bad Request"
+/* END HTTP SETTINGS */
+
+#define COND_PERROR_EXP(condition, function_name, expression) \
+ if (condition) { \
+ perror(function_name); \
+ expression; \
+ }
+
+int minibox_main(int argc, char **argv);
+int ascii_main(int argc, char **argv);
+int echo_main(int argc, char **argv);
+int http_main(int argc, char **argv);
+int lock_main(int argc, char **argv);
+int yes_main(int argc, char **argv);
+int cat_main(int argc, char **argv);
+int pwd_main(int argc, char **argv);
+int wc_main(int argc, char **argv);
+int ls_main(int argc, char **argv);
+int touch_main(int argc, char **argv);
+int ed_main(int argc, char **argv);
+
+int init_main(void);
diff --git a/userland/minibox/utilities/init.c b/userland/minibox/utilities/init.c
new file mode 100644
index 0000000..35bedf2
--- /dev/null
+++ b/userland/minibox/utilities/init.c
@@ -0,0 +1,72 @@
+#include <assert.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <pty.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <unistd.h>
+
+int cmdfd;
+
+void execsh(void) {
+ char *argv[] = {NULL};
+ execv("/sh", argv);
+}
+
+void newtty(void) {
+ int m;
+ int s;
+ openpty(&m, &s, NULL, NULL, NULL);
+ int pid = fork();
+ if (0 == pid) {
+ dup2(s, 0);
+ dup2(s, 1);
+ dup2(s, 2);
+ execsh();
+ return;
+ }
+ close(s);
+ cmdfd = m;
+}
+
+void shell() {
+ struct pollfd fds[2];
+ fds[0].fd = cmdfd;
+ fds[0].events = POLLIN;
+ fds[0].revents = 0;
+ fds[1].fd = open("/dev/keyboard", O_RDONLY, 0);
+ fds[1].events = POLLIN;
+ fds[1].revents = 0;
+ for (;; fds[0].revents = fds[1].revents = 0) {
+ poll(fds, 2, 0);
+ if (fds[0].revents & POLLIN) {
+ char c[4096];
+ int rc = read(fds[0].fd, c, 4096);
+ assert(rc > 0);
+ for (int i = 0; i < rc; i++)
+ putchar(c[i]);
+ }
+ if (fds[1].revents & POLLIN) {
+ char c;
+ int rc = read(fds[1].fd, &c, 1);
+ assert(rc > 0);
+ write(cmdfd, &c, 1);
+ // putchar(c);
+ }
+ }
+}
+
+int init_main(void) {
+ if (1 != getpid()) {
+ printf("minibox init must be launched as pid1.\n");
+ return 1;
+ }
+ if (fork())
+ for (;;)
+ wait(NULL);
+ char *a[] = {NULL};
+ execv("/term", a);
+ return 1;
+}
diff --git a/userland/minibox/utilities/ls.c b/userland/minibox/utilities/ls.c
new file mode 100644
index 0000000..dc93d36
--- /dev/null
+++ b/userland/minibox/utilities/ls.c
@@ -0,0 +1,42 @@
+#include "include.h"
+#include <dirent.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+int ls_main(int argc, char **argv) {
+ int list_hidden = 0;
+ int newline = 0;
+ /*
+ for (int ch;-1 != (ch = getopt(argc, argv, "a1"));)
+ switch ((char)ch)
+ {
+ case 'a':
+ list_hidden = 1;
+ break;
+ case '1':
+ newline = 1;
+ break;
+ }*/
+ struct dirent **namelist;
+ int n;
+ COND_PERROR_EXP(-1 == (n = scandir("/", &namelist, 0, 0)), "scandir",
+ return 1);
+
+ int prev = 0;
+ for (int i = 0; i < n; i++) {
+ if (!list_hidden)
+ if ('.' == *namelist[i]->d_name)
+ continue;
+
+ if (prev)
+ putchar(newline ? '\n' : ' ');
+ else
+ prev = 1;
+ printf("%s", namelist[i]->d_name);
+ }
+ putchar('\n');
+ return 0;
+}
diff --git a/userland/minibox/utilities/minibox.c b/userland/minibox/utilities/minibox.c
new file mode 100644
index 0000000..ec5fdbd
--- /dev/null
+++ b/userland/minibox/utilities/minibox.c
@@ -0,0 +1,15 @@
+#include "include.h"
+
+void usage(void);
+int main(int argc, char **argv);
+
+// Should a command be called via "minibox <command> <arguments>" then shift
+// argv and argc to become "<command> <arguments>" and rerun main()
+int minibox_main(int argc, char **argv) {
+ if (argc < 2)
+ usage();
+
+ argc--;
+ argv++;
+ return main(argc, argv);
+}
diff --git a/userland/minibox/utilities/pwd.c b/userland/minibox/utilities/pwd.c
new file mode 100644
index 0000000..29d8129
--- /dev/null
+++ b/userland/minibox/utilities/pwd.c
@@ -0,0 +1,12 @@
+#include "include.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <limits.h>
+
+int pwd_main(int argc, char **argv) {
+ char cwd[PATH_MAX];
+ COND_PERROR_EXP(NULL == (getcwd(cwd, PATH_MAX)), "getcwd", return 1);
+ puts(cwd);
+ return 0;
+}
diff --git a/userland/minibox/utilities/touch.c b/userland/minibox/utilities/touch.c
new file mode 100644
index 0000000..949ad96
--- /dev/null
+++ b/userland/minibox/utilities/touch.c
@@ -0,0 +1,11 @@
+#include "include.h"
+#include <fcntl.h>
+
+int touch_main(int argc, char **argv) {
+ if (argc < 2)
+ return 1;
+ int fd;
+ COND_PERROR_EXP(open(argv[1], 0, O_CREAT), "open", return 1)
+ close(fd);
+ return 0;
+}
diff --git a/userland/minibox/utilities/wc.c b/userland/minibox/utilities/wc.c
new file mode 100644
index 0000000..886eb9e
--- /dev/null
+++ b/userland/minibox/utilities/wc.c
@@ -0,0 +1,106 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include "include.h"
+
+int cmode, wmode, lmode;
+
+void output(const char * str, size_t lines, size_t words, size_t chars)
+{
+ if(lmode)
+ printf("%d", lines);
+
+ if(wmode)
+ {
+ if(lmode) putchar(' ');
+
+ printf("%d", words);
+ }
+
+ if(cmode)
+ {
+ if(lmode) putchar(' ');
+
+ printf("%d", chars);
+ }
+
+ if(str) printf(" %s", str);
+
+ putchar('\n');
+}
+
+void wc(int argc, char ** argv)
+{
+ int fd = fd_stdin;
+ size_t total_chars, total_words, total_lines;
+ total_chars = total_words = total_lines = 0;
+
+ if(NULL == *argv)
+ goto read_stdin;
+
+
+ for(;*argv;argv++)
+ {
+ int new_word = 1;
+ size_t chars = 0,
+ words = chars,
+ lines = chars;
+
+ fd = open(*argv, O_RDONLY, 0);
+read_stdin:
+ for(char c;read(fd, &c, 1);)
+ {
+ if(cmode)
+ chars++;
+
+ if(wmode)
+ {
+ if(isspace(c)) {
+ new_word = 1;
+ } else if(new_word) {
+ words++;
+ new_word = 0;
+ }
+ }
+
+ if(lmode)
+ if('\n' == c)
+ lines++;
+ }
+ close(fd);
+ if(lmode) total_lines += lines;
+ if(wmode) total_words += words;
+ if(cmode) total_chars += chars;
+
+ output(*argv, lines, words, chars);
+ if(NULL == *argv) return; // We read from stdin
+ }
+
+ if(argc > 1) output("total", total_lines, total_words, total_chars);
+}
+
+int wc_main(int argc, char ** argv)
+{
+ cmode = wmode = lmode = 0;
+ for(argc--;*++argv && '-' == **argv;argc--)
+ switch(*(*argv+1))
+ {
+ case 'l':
+ lmode = 1;
+ break;
+ case 'w':
+ wmode = 1;
+ break;
+ case 'c':
+ cmode = 1;
+ break;
+ }
+
+ if(!(lmode || cmode || wmode))
+ cmode = wmode = lmode = 1;
+
+ wc(argc, argv);
+ return 0;
+}
diff --git a/userland/minibox/utilities/yes.c b/userland/minibox/utilities/yes.c
new file mode 100644
index 0000000..ff19004
--- /dev/null
+++ b/userland/minibox/utilities/yes.c
@@ -0,0 +1,13 @@
+#include "include.h"
+#include <stdio.h>
+
+int yes_main(int argc, char **argv) {
+ if (argc < 2)
+ for (;;)
+ puts("y");
+
+ for (;; putchar('\n'))
+ for (int i = 1; i < argc; i++)
+ printf("%s ", argv[i]);
+ return 0;
+}
diff --git a/userland/sh/Makefile b/userland/sh/Makefile
new file mode 100644
index 0000000..adccfb3
--- /dev/null
+++ b/userland/sh/Makefile
@@ -0,0 +1,13 @@
+CC="/home/anton/prj/osdev/sysroot/bin/i686-sb-gcc"
+CFLAGS = -ggdb -ffreestanding -O0 -Wall -Wextra -pedantic -mgeneral-regs-only -Wimplicit-fallthrough -fsanitize=shift,signed-integer-overflow,bounds
+BINS=sh
+all: $(BINS)
+
+sh.o: sh.c
+ $(CC) $(CFLAGS) -L../libc/ -lc -c sh.c -I../libc/
+# $(CC) $(CFLAGS) ../libc/libc.o ../libc/crt0.o sh.c -I../libc/
+
+clean:
+ rm sh sh.o
+sh: sh.o
+ $(CC) -shared -o sh -ffreestanding -nostdlib $(CFLAGS) sh.o -L../libc/ -lc -lgcc #-L../libc/c.a
diff --git a/userland/sh/sh b/userland/sh/sh
new file mode 100755
index 0000000..7791495
--- /dev/null
+++ b/userland/sh/sh
Binary files differ
diff --git a/userland/sh/sh.c b/userland/sh/sh.c
new file mode 100644
index 0000000..5fe7f63
--- /dev/null
+++ b/userland/sh/sh.c
@@ -0,0 +1,224 @@
+#include <assert.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <poll.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#define MAX_ARGS 20
+
+#define IS_SPECIAL(_c) (';' == _c || '\n' == _c || '&' == _c || '|' == _c)
+
+char *PATH = "/:/bin";
+
+int can_open(char *f) {
+ int rc;
+ if (-1 == (rc = open(f, O_RDONLY, 0)))
+ return 0;
+ close(rc);
+ return 1;
+}
+
+int find_path(char *file, char *buf) {
+ if ('/' == *file || '.' == *file) { // Real path
+ if (!can_open(file)) {
+ return 0;
+ }
+ strcpy(buf, file);
+ return 1;
+ }
+
+ char *p = PATH;
+ for (;;) {
+ char *b = p;
+ for (; *p && ':' != *p; p++)
+ ;
+ size_t l = p - b;
+ strlcpy(buf, b, l);
+ strcat(buf, "/");
+ strcat(buf, file);
+ if (can_open(buf)) {
+ return 1;
+ }
+ if (!*p)
+ break;
+ p++;
+ }
+ return 0;
+}
+
+int internal_exec(char *file, char **argv) {
+ char r_path[PATH_MAX];
+ if (!find_path(file, r_path))
+ return 0;
+ if (-1 == execv(r_path, argv)) {
+ perror("exec");
+ return 0;
+ }
+ return 1;
+}
+
+int execute_program(char *s, size_t l, int ignore_rc, int f_stdout,
+ int *new_out) {
+ if (!l)
+ return -1;
+
+ char c[l + 1];
+ memcpy(c, s, l);
+ c[l] = 0;
+
+ char *argv[MAX_ARGS];
+ int args = 0;
+ char *p = c;
+ for (size_t i = 0; i <= l; i++) {
+ if (' ' == c[i]) {
+ if (p == c + i) {
+ for (; ' ' == *p; p++, i++)
+ ;
+ i--;
+ continue;
+ }
+ c[i] = '\0';
+
+ if (strlen(p) == 0)
+ break;
+
+ argv[args] = p;
+ args++;
+ p = c + i + 1;
+ } else if (i == l) {
+ if (strlen(p) == 0)
+ break;
+ argv[args] = p;
+ args++;
+ }
+ }
+ argv[args] = NULL;
+
+ int fd[2];
+ pipe(fd);
+
+ int pid = fork();
+ if (0 == pid) {
+ if (new_out)
+ dup2(fd[1], 1);
+ if (-1 != f_stdout)
+ dup2(f_stdout, 0);
+ close(fd[0]);
+ if (!internal_exec(argv[0], argv)) {
+ printf("exec failed\n");
+ exit(1);
+ }
+ }
+
+ close(fd[1]);
+ if (new_out)
+ *new_out = fd[0];
+
+ if (ignore_rc)
+ return 0;
+
+ int rc;
+ wait(&rc);
+ return rc;
+}
+
+int compute_expression(char *exp) {
+ char *n = exp;
+ int ignore_next = 0;
+ int rc;
+ int f_stdout = -1;
+ int new_out = f_stdout;
+ for (; *exp; exp++) {
+ if (!IS_SPECIAL(*exp)) {
+ continue;
+ }
+ if ('\n' == *exp)
+ break;
+ if (';' == *exp) {
+ if (!ignore_next) {
+ execute_program(n, exp - n, 0, f_stdout, NULL);
+ }
+ n = exp + 1;
+ continue;
+ }
+ if ('&' == *exp && '&' == *(exp + 1)) {
+ if (!ignore_next) {
+ rc = execute_program(n, exp - n, 0, f_stdout, NULL);
+ if (0 != rc)
+ ignore_next = 1;
+ }
+ n = exp + 2;
+ exp++;
+ continue;
+ } else if ('&' == *exp) {
+ if (!ignore_next) {
+ execute_program(n, exp - n, 1, f_stdout, NULL);
+ }
+ n = exp + 1;
+ continue;
+ }
+ if ('|' == *exp && '|' == *(exp + 1)) {
+ if (!ignore_next) {
+ rc = execute_program(n, exp - n, 0, f_stdout, NULL);
+ if (0 == rc)
+ ignore_next = 1;
+ }
+ n = exp + 2;
+ exp++;
+ continue;
+ } else if ('|' == *exp) {
+ if (!ignore_next) {
+ execute_program(n, exp - n, 1, f_stdout, &new_out);
+ f_stdout = new_out;
+ }
+ n = exp + 1;
+ continue;
+ }
+ }
+ if (!ignore_next)
+ rc = execute_program(n, exp - n, 0, f_stdout, NULL);
+ return rc;
+}
+
+char *get_line(void) {
+ char *str = malloc(1024);
+ char *p = str;
+ int rc;
+ for (;;) {
+ if (0 == (rc = read(0, p, 1))) {
+ continue;
+ }
+ if (0 > rc) {
+ perror("read");
+ continue;
+ }
+ if (8 == *p) {
+ if (p == str)
+ continue;
+ putchar(*p);
+ p--;
+ continue;
+ }
+ putchar(*p);
+ if ('\n' == *p) {
+ break;
+ }
+ p++;
+ }
+ p++;
+ *p = '\0';
+ return str;
+}
+
+int main(void) {
+ for (;;) {
+ printf("/ : ");
+ char *l = get_line();
+ compute_expression(l);
+ free(l);
+ }
+ return 0;
+}
diff --git a/userland/sh/sh_a b/userland/sh/sh_a
new file mode 100755
index 0000000..7b435ab
--- /dev/null
+++ b/userland/sh/sh_a
Binary files differ
diff --git a/userland/sh/sh_bad b/userland/sh/sh_bad
new file mode 100755
index 0000000..7f93418
--- /dev/null
+++ b/userland/sh/sh_bad
Binary files differ
diff --git a/userland/snake/Makefile b/userland/snake/Makefile
new file mode 100644
index 0000000..f29df30
--- /dev/null
+++ b/userland/snake/Makefile
@@ -0,0 +1,15 @@
+CC="/home/anton/prj/osdev/sysroot/bin/i686-sb-gcc"
+CFLAGS = -ggdb -ffreestanding -O0 -Wall -Wextra -pedantic -mgeneral-regs-only -Wimplicit-fallthrough -static -fsanitize=shift,signed-integer-overflow,bounds
+LIB=-L../libgui -lgui -L../json -ljson -L../libc -lc -lgcc
+INC=-I../libc/ -I../json/ -I../libgui/
+BINS=snake
+all: $(BINS)
+
+snake.o: snake.c
+ $(CC) $(CFLAGS) $(INC) $(LIB) -o $@ -c $<
+
+snake: snake.o
+ $(CC) -nostdlib $(CFLAGS) -o $@ $^ $(LIB)
+
+clean:
+ rm $(BINS) *.o
diff --git a/userland/snake/snake.c b/userland/snake/snake.c
new file mode 100644
index 0000000..7bfb312
--- /dev/null
+++ b/userland/snake/snake.c
@@ -0,0 +1,109 @@
+#include <assert.h>
+#include <fcntl.h>
+#include <json.h>
+#include <libgui.h>
+#include <poll.h>
+#include <pty.h>
+#include <socket.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+GUI_Window *global_w;
+
+#define SNAKE_WIDTH 10
+
+int get_key_event(char *c) {
+ if (0 >= read(global_w->ws_socket, c, 1))
+ return 0;
+ if (0 == *c)
+ return 0;
+ return 1;
+}
+
+void draw_snake(int x, int y) {
+ int sx = global_w->sx;
+ uint32_t *b = &global_w->bitmap_ptr[y * sx + x];
+ for (int i = 0; i < SNAKE_WIDTH; i++) {
+ for (int j = 0; j < SNAKE_WIDTH; j++) {
+ b[j] = 0xFF00FF;
+ }
+ b += sx;
+ }
+}
+
+int clamp(int *x, int *y) {
+ int clamped = 0;
+ if (*x + SNAKE_WIDTH > global_w->sx) {
+ *x = global_w->sx - SNAKE_WIDTH;
+ clamped = 1;
+ }
+ if (*y + SNAKE_WIDTH > global_w->sy) {
+ *y = global_w->sy - SNAKE_WIDTH;
+ clamped = 1;
+ }
+ return clamped;
+}
+
+void loop() {
+ int vel = SNAKE_WIDTH;
+ static int y_dir = SNAKE_WIDTH;
+ static int x_dir = 0;
+ static int snake_x = 10;
+ static int snake_y = 10;
+ static int ticks = 0;
+ ticks++;
+ char c;
+ if (get_key_event(&c)) {
+ switch (c) {
+ case 'w':
+ y_dir = -1 * vel;
+ x_dir = 0;
+ break;
+ case 's':
+ y_dir = vel;
+ x_dir = 0;
+ break;
+ case 'a':
+ x_dir = -1 * vel;
+ y_dir = 0;
+ break;
+ case 'd':
+ x_dir = vel;
+ y_dir = 0;
+ break;
+ case 'q':
+ exit(0);
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (!(ticks > 5))
+ return;
+ ticks = 0;
+
+ snake_x += x_dir;
+ snake_y += y_dir;
+ if (clamp(&snake_x, &snake_y))
+ return;
+ draw_snake(snake_x, snake_y);
+ if (y_dir || x_dir)
+ GUI_UpdateWindow(global_w);
+}
+
+int main(void) {
+ global_w = GUI_CreateWindow(10, 10, 150 * 4, 150 * 4);
+ assert(global_w);
+ for (int i = 0; i < 150 * 150 * 4 * 4; i++)
+ global_w->bitmap_ptr[i] = 0xFFFFFF;
+ GUI_UpdateWindow(global_w);
+ for (;;) {
+ loop();
+ msleep(50);
+ }
+ return 0;
+}
diff --git a/userland/terminal/Makefile b/userland/terminal/Makefile
new file mode 100644
index 0000000..330f6e0
--- /dev/null
+++ b/userland/terminal/Makefile
@@ -0,0 +1,15 @@
+CC="/home/anton/prj/osdev/sysroot/bin/i686-sb-gcc"
+CFLAGS = -ggdb -ffreestanding -O0 -Wall -Wextra -pedantic -mgeneral-regs-only -Wimplicit-fallthrough -static -fsanitize=shift,signed-integer-overflow,bounds
+LIB=-L../libgui -lgui -L../json -ljson -L../libc -lc -lgcc
+INC=-I../libc/ -I../json/ -I../libgui/
+BINS=term
+all: $(BINS)
+
+term.o: term.c
+ $(CC) $(CFLAGS) $(INC) $(LIB) -o $@ -c $<
+
+term: term.o
+ $(CC) -nostdlib $(CFLAGS) -o $@ $^ $(LIB)
+
+clean:
+ rm $(BINS) *.o
diff --git a/userland/terminal/term.c b/userland/terminal/term.c
new file mode 100644
index 0000000..8a2ae83
--- /dev/null
+++ b/userland/terminal/term.c
@@ -0,0 +1,166 @@
+#include <assert.h>
+#include <fcntl.h>
+#include <json.h>
+#include <libgui.h>
+#include <poll.h>
+#include <pty.h>
+#include <socket.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#define TERM_BACKGROUND 0x000000
+
+int cmdfd;
+GUI_Window *global_w;
+uint32_t screen_pos_x = 0;
+uint32_t screen_pos_y = 0;
+int serial_fd;
+
+void execsh(void) {
+ char *argv[] = {NULL};
+ execv("/sh", argv);
+}
+
+uint32_t cursor_pos_x = 0;
+uint32_t cursor_pos_y = 0;
+
+void screen_remove_old_cursor() {
+ GUI_OverwriteFont(global_w, cursor_pos_x, cursor_pos_y, TERM_BACKGROUND);
+}
+
+void screen_update_cursor() {
+ GUI_OverwriteFont(global_w, screen_pos_x, screen_pos_y, 0xFFFFFF);
+ cursor_pos_x = screen_pos_x;
+ cursor_pos_y = screen_pos_y;
+}
+
+void screen_putchar(uint32_t c) {
+ if (c == '\n') {
+ screen_pos_x = 0;
+ screen_pos_y += 8;
+ screen_remove_old_cursor();
+ screen_update_cursor();
+ return;
+ }
+ if (screen_pos_y > global_w->sy - 8) {
+ uint8_t line[global_w->sx * sizeof(uint32_t)];
+ for (int i = 0; i < global_w->sy - 8; i++) {
+ memcpy(line, global_w->bitmap_ptr + ((i + 8) * global_w->sx),
+ global_w->sx * sizeof(uint32_t));
+ memcpy(global_w->bitmap_ptr + (i * global_w->sx), line,
+ global_w->sx * sizeof(uint32_t));
+ }
+ for (int i = 0; i < global_w->sx; i += 8) {
+ GUI_OverwriteFont(global_w, i, screen_pos_y - 8, TERM_BACKGROUND);
+ }
+ screen_pos_x = 0;
+ screen_pos_y -= 8;
+ }
+ GUI_DrawFont(global_w, screen_pos_x, screen_pos_y, c);
+ screen_pos_x += 8;
+ if (screen_pos_x >= global_w->sx - 8) {
+ screen_pos_x = 0;
+ screen_pos_y += 8;
+ }
+ screen_update_cursor();
+}
+
+void screen_delete_char(void) {
+ GUI_OverwriteFont(global_w, screen_pos_x, screen_pos_y, TERM_BACKGROUND);
+ screen_pos_x -= 8;
+ GUI_OverwriteFont(global_w, screen_pos_x, screen_pos_y, TERM_BACKGROUND);
+ screen_update_cursor();
+}
+
+void screen_print(const unsigned char *s, int l) {
+ for (; l; l--, s++) {
+ if ('\b' == *s) {
+ screen_delete_char();
+ continue;
+ }
+ screen_putchar((uint32_t)*s);
+ }
+}
+
+void newtty(void) {
+ int m;
+ int s;
+ openpty(&m, &s, NULL, NULL, NULL);
+ int pid = fork();
+ if (0 == pid) {
+ dup2(s, 0);
+ dup2(s, 1);
+ dup2(s, 2);
+ execsh();
+ return;
+ }
+ close(s);
+ cmdfd = m;
+}
+
+void writetty(const char *b, size_t len) {
+ write(serial_fd, b, len);
+ for (int rc; len; len -= rc) {
+ rc = write(cmdfd, b, len);
+ if (-1 == rc) {
+ perror("write");
+ assert(0);
+ }
+ }
+}
+
+void run() {
+ char buffer[4096];
+ struct pollfd fds[2];
+ fds[0].fd = cmdfd;
+ fds[0].events = POLLIN;
+ fds[0].revents = 0;
+ fds[1].fd = global_w->ws_socket;
+ fds[1].events = POLLIN;
+ fds[1].revents = 0;
+ for (;; fds[0].revents = fds[1].revents = 0) {
+ poll(fds, 2, 0);
+ if (fds[0].revents & POLLIN) {
+ int rc;
+ if ((rc = read(cmdfd, buffer, 4096))) {
+ screen_print(buffer, rc);
+ GUI_UpdateWindow(global_w);
+ }
+ }
+ if (fds[1].revents & POLLIN) {
+ WS_EVENT e;
+ int rc;
+ if (0 >= (rc = read(global_w->ws_socket, &e, sizeof(e))))
+ continue;
+ if (1 == e.ev.release)
+ continue;
+ if (0 == e.ev.c)
+ continue;
+ write(cmdfd, &e.ev.c, 1);
+ }
+ }
+}
+
+int main(void) {
+ open("/dev/serial", O_RDWR, 0);
+ open("/dev/serial", O_RDWR, 0);
+ printf("running the terminal\n");
+ int pid = fork();
+ if (0 == pid) {
+ char *argv[] = {NULL};
+ execv("/ws", argv);
+ }
+
+ global_w = GUI_CreateWindow(20, 20, 250 * 4, 150 * 4);
+ assert(global_w);
+ for (int i = 0; i < 250 * 150 * 4 * 4; i++)
+ global_w->bitmap_ptr[i] = TERM_BACKGROUND;
+ // memset(global_w->bitmap_ptr, 0x0, 50 * 50);
+ GUI_UpdateWindow(global_w);
+ newtty();
+ run();
+ return 0;
+}
diff --git a/userland/test/Makefile b/userland/test/Makefile
new file mode 100644
index 0000000..7287939
--- /dev/null
+++ b/userland/test/Makefile
@@ -0,0 +1,16 @@
+#CC="/home/anton/opt/cross/bin/i686-elf-gcc"
+CC="/home/anton/prj/osdev/sysroot/bin/i686-sb-gcc"
+CFLAGS = -O2 -Wall -Wextra -pedantic -Wimplicit-fallthrough -static
+LIB=-L../json -L../json/hashmap -ljson -lhashmap
+INC=-I../json/
+BINS=test
+all: $(BINS)
+
+test.o: test.c
+ $(CC) $(CFLAGS) $(INC) $(LIB) -o $@ -c $<
+
+test: test.o
+ $(CC) $(CFLAGS) -o $@ $^ $(LIB)
+
+clean:
+ rm test.o test
diff --git a/userland/test/linux.sh b/userland/test/linux.sh
new file mode 100755
index 0000000..d40d6cc
--- /dev/null
+++ b/userland/test/linux.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+gcc -DLINUX test.c -o ./local/a.out
+cd local
+./a.out
diff --git a/userland/test/local/a.out b/userland/test/local/a.out
new file mode 100755
index 0000000..1069f1f
--- /dev/null
+++ b/userland/test/local/a.out
Binary files differ
diff --git a/userland/test/local/testfile b/userland/test/local/testfile
new file mode 100644
index 0000000..629ae5e
--- /dev/null
+++ b/userland/test/local/testfile
@@ -0,0 +1 @@
+ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvxyz
diff --git a/userland/test/test b/userland/test/test
new file mode 100755
index 0000000..63f9d8b
--- /dev/null
+++ b/userland/test/test
Binary files differ
diff --git a/userland/test/test.c b/userland/test/test.c
new file mode 100644
index 0000000..041b08a
--- /dev/null
+++ b/userland/test/test.c
@@ -0,0 +1,722 @@
+#include <assert.h>
+#include <fcntl.h>
+//#include <json.h>
+#include <ctype.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if 1
+void dbgln(const char *fmt) { printf("%s\n", fmt); }
+#else
+void dbgln(const char *fmt, ...) {
+ printf("| ");
+ va_list ap;
+ va_start(ap, fmt);
+ int rc = vdprintf(1, fmt, ap);
+ va_end(ap);
+ printf("\n");
+}
+#endif
+
+void isx_test() {
+ dbgln("isx TEST");
+ {
+ assert(isspace(' '));
+ assert(isspace('\t'));
+ assert(!isspace('A'));
+
+ assert(isalpha('A'));
+ assert(!isalpha('9'));
+ assert(!isalpha(' '));
+ assert(!isalpha('z' + 1));
+
+ assert(isascii('A'));
+ assert(isascii('9'));
+ assert(isascii(' '));
+ assert(!isascii(0xFF));
+
+ assert(ispunct('.'));
+ assert(!ispunct('A'));
+
+ assert(isdigit('9'));
+ assert(!isdigit('A'));
+ }
+ dbgln("isx TEST PASSED");
+}
+
+void malloc_test(void) {
+ dbgln("malloc TEST");
+ for (int j = 0; j < 100; j++) {
+ // printf("j : %x\n", j);
+ uint8_t *t = malloc(400 + j);
+ memset(t, 0x43 + (j % 10), 400 + j);
+ uint8_t *p = malloc(900 + j);
+ memset(p, 0x13 + (j % 10), 900 + j);
+ assert(p > t && p > (t + 400 + j));
+
+ for (int i = 0; i < 400 + j; i++)
+ if (t[i] != 0x43 + (j % 10)) {
+ printf("t addy: %x, val: %x, should be: %x\n", t + i, t[i],
+ 0x43 + (j % 10));
+ assert(0);
+ }
+
+ for (int i = 0; i < 900 + j; i++)
+ if (p[i] != 0x13 + (j % 10)) {
+ printf("p addy: %x, val: %x, should be: %x\n", p + i, t[i],
+ 0x13 + (j % 10));
+ assert(0);
+ }
+ free(t);
+ }
+ dbgln("malloc TEST PASSED");
+}
+
+void memcmp_test(void) {
+ dbgln("memcmp TEST");
+ {
+ assert(0 == memcmp("\xAA\xBB\xCC", "\xAA\xBB\xCC", 3));
+ assert(1 == memcmp("\xAF\xBB\xCC", "\xAA\xBB\xCC", 3));
+ }
+ dbgln("memcmp TEST PASSED");
+}
+
+void memcpy_test(void) {
+ dbgln("memcpy TEST");
+ {
+ char buf[100];
+ assert(buf == memcpy(buf, "\xAA\xBB\xCC", 3));
+ assert(0 == memcmp(buf, "\xAA\xBB\xCC", 3));
+ assert(buf == memcpy(buf, "\xCC\xBB\xCC", 3));
+ assert(0 == memcmp(buf, "\xCC\xBB\xCC", 3));
+
+ assert(buf == memcpy(buf, "\xAA\xBB\xCC\xDD", 4));
+ assert(0 == memcmp(buf, "\xAA\xBB\xCC\xDD", 4));
+ assert(buf == memcpy(buf, "\xAA\xBB\xCC\xEE", 3));
+ assert(0 == memcmp(buf, "\xAA\xBB\xCC\xDD", 4));
+ }
+ dbgln("memcpy TEST PASSED");
+}
+
+void memmove_test(void) {
+ dbgln("memmove TEST");
+ {
+ char buf[100];
+ memcpy(buf, "foobar", 6);
+ const char *p = buf + 2; // obar
+
+ assert(buf == memmove(buf, p, 4));
+ assert(0 == memcmp(buf, "obarar", 6));
+ }
+ dbgln("memmove TEST PASSED");
+}
+
+void strlen_test(void) {
+ dbgln("strlen TEST");
+ {
+ assert(0 == strlen(""));
+ assert(3 == strlen("%is"));
+ assert(3 == strlen("foo"));
+ assert(3 == strlen("bar"));
+ assert(6 == strlen("foobar"));
+ }
+ dbgln("strlen TEST PASSED");
+}
+
+void strnlen_test(void) {
+ dbgln("strnlen TEST");
+ {
+ assert(0 == strnlen("", 0));
+ assert(0 == strnlen("", 3));
+ assert(3 == strnlen("foo", 3));
+ assert(2 == strnlen("bar", 2));
+ assert(3 == strnlen("foobar", 3));
+ assert(6 == strnlen("foobar", 6));
+ assert(6 == strnlen("foobar", 8));
+ }
+ dbgln("strnlen TEST PASSED");
+}
+
+/*
+void json_test(void) {
+ dbgln("JSON TEST");
+ {
+ const char *s = "{\"string\": \"hello\", \"object\": {\"string\": \"ff\"}}";
+ JSON_CTX ctx;
+ JSON_Init(&ctx);
+ JSON_Parse(&ctx, s);
+ JSON_ENTRY *main_entry = JSON_at(&ctx.global_object, 0);
+ assert(main_entry != NULL);
+ JSON_ENTRY *index_entry = JSON_at(main_entry, 0);
+ JSON_ENTRY *string_entry = JSON_search_name(main_entry, "string");
+ assert(index_entry != NULL);
+ assert(index_entry == string_entry);
+ char *str = index_entry->value;
+ assert(0 == strcmp(str, "hello"));
+
+ JSON_ENTRY *object = JSON_search_name(main_entry, "object");
+ assert(object != NULL);
+ JSON_ENTRY *object_string = JSON_search_name(object, "string");
+ assert(object_string != NULL);
+ assert(0 == strcmp(object_string->value, "ff"));
+ }
+ dbgln("JSON TEST PASSED");
+}*/
+
+void random_test(void) {
+ dbgln("/dev/random TEST");
+ {
+ int fd = open("/dev/random", O_RDONLY, 0);
+ uint8_t buffer_1[256];
+ assert(256 == read(fd, buffer_1, 256));
+ close(fd);
+ fd = open("/dev/random", O_RDONLY, 0);
+ uint8_t buffer_2[256];
+ assert(256 == read(fd, buffer_2, 256));
+ close(fd);
+ assert(0 != memcmp(buffer_1, buffer_2, 256));
+ }
+ dbgln("/dev/random TEST PASSED");
+}
+
+void sscanf_test(void) {
+ dbgln("sscanf TEST");
+ {
+ int d1;
+ int d2;
+ sscanf("1337:7331", "%d:%d", &d1, &d2);
+ assert(1337 == d1);
+ assert(7331 == d2);
+ sscanf(" 1234 31415", "%d%d", &d1, &d2);
+ assert(1234 == d1);
+ assert(31415 == d2);
+ sscanf(" 1234 441122", "%*d%d", &d1);
+ assert(441122 == d1);
+
+ char f;
+ char b;
+ sscanf("f:b", "%c:%c", &f, &b);
+ assert('f' == f);
+ assert('b' == b);
+ }
+ dbgln("sscanf TEST PASSED");
+}
+
+void strtoul_test(void) {
+ dbgln("strtoul TEST");
+ {
+ long r;
+ char *s = "1234";
+ char *endptr;
+ r = strtoul("1234", &endptr, 10);
+ assert(1234 == r);
+ assert(endptr == (s + 4));
+ }
+ dbgln("strtoul TEST PASSED");
+}
+
+void strcspn_test(void) {
+ dbgln("strcspn TEST");
+ {
+ assert(4 == strcspn("1234", ""));
+ assert(3 == strcspn("1234", "4"));
+ assert(2 == strcspn("1234", "43"));
+ assert(0 == strcspn("1234", "2143"));
+ }
+ dbgln("strcspn TEST PASSED");
+}
+
+void strpbrk_test(void) {
+ dbgln("strpbrk TEST");
+ {
+ char *s = "01234";
+ assert(s + 3 == strpbrk(s, "3"));
+ assert(s + 4 == strpbrk(s, "4"));
+ assert(s + 2 == strpbrk(s, "2"));
+ assert(s + 2 == strpbrk(s, "23"));
+ assert(NULL == strpbrk(s, "5"));
+ }
+ dbgln("strpbrk TEST PASSED");
+}
+
+void strcpy_test(void) {
+ dbgln("strcpy TEST");
+ {
+ char buf[10];
+ memset(buf, '\xBB', 10);
+ strcpy(buf, "hello");
+ assert(0 == memcmp(buf, "hello\0\xBB\xBB\xBB\xBB", 10));
+ }
+ dbgln("strcpy TEST PASSED");
+}
+
+void strncpy_test(void) {
+ dbgln("strncpy TEST");
+ {
+ char buf[10];
+ memset(buf, '\xBB', 10);
+ strncpy(buf, "hello", 3);
+ assert(0 == memcmp(buf, "hel\xBB\xBB\xBB\xBB\xBB\xBB\xBB", 10));
+ strncpy(buf, "hello", 6);
+ assert(0 == memcmp(buf, "hello\0\xBB\xBB\xBB\xBB", 10));
+ }
+ dbgln("strncpy TEST PASSED");
+}
+
+void strlcpy_test(void) {
+ dbgln("strlcpy TEST");
+ {
+ char buf[10];
+ memset(buf, '\xBB', 10);
+ strlcpy(buf, "hello", 3);
+ assert(0 == memcmp(buf, "hel\x00\xBB\xBB\xBB\xBB\xBB\xBB", 10));
+ }
+ dbgln("strlcpy TEST PASSED");
+}
+
+void strcat_test(void) {
+ dbgln("strcat TEST");
+ {
+ char buf[10];
+ memset(buf, '\xBB', 10);
+ strcpy(buf, "hel");
+ assert(0 == memcmp(buf, "hel\0\xBB\xBB\xBB\xBB\xBB\xBB", 10));
+ strcat(buf, "lo");
+ assert(0 == memcmp(buf, "hello\0\xBB\xBB\xBB\xBB", 10));
+ }
+ dbgln("strcat TEST PASSED");
+}
+
+void strchr_test(void) {
+ dbgln("strchr TEST");
+ {
+ char *s = "0123412345";
+ assert(s + 3 == strchr(s, '3'));
+ assert(s + 4 + 5 == strchr(s, '5'));
+ assert(s + 4 == strchr(s, '4'));
+ assert(NULL == strchr(s, '9'));
+ }
+ dbgln("strchr TEST PASSED");
+}
+
+void strrchr_test(void) {
+ dbgln("strrchr TEST");
+ {
+ char *s = "0123412345";
+ assert(s + 3 + 4 == strrchr(s, '3'));
+ assert(s == strrchr(s, '0'));
+ assert(s + 4 + 5 == strrchr(s, '5'));
+ assert(NULL == strrchr(s, '9'));
+ }
+ dbgln("strrchr TEST PASSED");
+}
+
+void strdup_test(void) {
+ dbgln("strdup TEST");
+ {
+ char *s;
+ s = strdup("hello");
+ assert(s);
+ assert(0 == strcmp(s, "hello"));
+ free(s);
+
+ s = strdup("abc");
+ assert(s);
+ assert(0 == strcmp(s, "abc"));
+ free(s);
+ }
+ dbgln("strdup TEST PASSED");
+}
+
+void strndup_test(void) {
+ dbgln("strdup TEST");
+ {
+ char *s;
+ s = strndup("hello", 5);
+ assert(s);
+ assert(0 == strcmp(s, "hello"));
+ free(s);
+
+ s = strndup("hello", 3);
+ assert(s);
+ assert(0 == strcmp(s, "hel"));
+ free(s);
+ }
+ dbgln("strndup TEST PASSED");
+}
+
+void abs_test(void) {
+ dbgln("abs TEST");
+ {
+ assert(1 == abs(1));
+ assert(1 == abs(-1));
+ assert(0 == abs(0));
+ }
+ dbgln("abs TEST PASSED");
+}
+
+void strspn_test(void) {
+ dbgln("strspn TEST");
+ {
+ assert(0 == strspn("abc", ""));
+ assert(0 == strspn("abc", "xyz"));
+ assert(1 == strspn("abc", "a"));
+ assert(2 == strspn("abc", "ab"));
+ assert(3 == strspn("abcd", "abc"));
+ assert(3 == strspn("abcde", "abce"));
+ }
+ dbgln("strspn TEST PASSED");
+}
+
+void strtol_test(void) {
+ dbgln("strtol TEST");
+ {
+ char *s = "1234";
+ char *e;
+ long r;
+ assert(1234 == strtol(s, &e, 10));
+ assert(e == (s + 4));
+ }
+ dbgln("strtol TEST PASSED");
+}
+
+void strcmp_test(void) {
+#define EQ(_s1) \
+ { assert(0 == strcmp(_s1, _s1)); }
+ dbgln("strcmp TEST");
+ {
+ EQ("hello, world");
+ EQ("");
+ EQ("int: 100, hex: 64, octal: 144 a");
+ }
+ dbgln("strcmp TEST PASSED");
+}
+
+void strncmp_test(void) {
+ dbgln("strncmp TEST");
+ {
+ assert(0 == strncmp("hello", "hello", 5));
+ assert(0 < strncmp("foo", "bar", 3));
+ assert(0 == strncmp("foobar", "foofoo", 3));
+ }
+ dbgln("strncmp TEST PASSED");
+}
+
+void strcasecmp_test(void) {
+ dbgln("strcasecmp TEST");
+ {
+ assert(0 == strcasecmp("foobar", "FOObar"));
+ assert(0 == strcasecmp("foobar", "foobar"));
+ assert(6 == strcasecmp("foobar", "bar"));
+ }
+ dbgln("strcasecmp TEST PASSED");
+}
+
+void strncasecmp_test(void) {
+ dbgln("strncasecmp TEST");
+ {
+ assert(0 == strncasecmp("foobar", "FOObar", 6));
+ assert(0 == strncasecmp("foobar", "foobar", 6));
+ assert(0 == strncasecmp("foo", "foobar", 3));
+ assert(-1 == strncasecmp("foo", "foobar", 4));
+ }
+ dbgln("strncasecmp TEST PASSED");
+}
+
+void strstr_test(void) {
+ dbgln("strstr TEST");
+ {
+ const char *a = "foobar123";
+ const char *b = "bar";
+ assert(a + 3 == strstr(a, b));
+ }
+ dbgln("strstr TEST PASSED");
+}
+
+void strtok_test(void) {
+ dbgln("strtok TEST");
+ {
+ char *s = "hello,world,goodbye";
+ assert(0 == strcmp(strtok(s, ","), "hello"));
+ assert(0 == strcmp(strtok(NULL, ","), "world"));
+ assert(0 == strcmp(strtok(NULL, ","), "goodbye"));
+ assert(NULL == strtok(NULL, ","));
+ char *s2 = "hello,,world,,goodbye,test";
+ assert(0 == strcmp(strtok(s2, ",,"), "hello"));
+ assert(0 == strcmp(strtok(NULL, ",,"), "world"));
+ assert(0 == strcmp(strtok(NULL, ","), "goodbye"));
+ assert(0 == strcmp(strtok(NULL, ","), "test"));
+ assert(NULL == strtok(NULL, ","));
+ }
+ dbgln("strtok TEST PASSED");
+}
+
+void fseek_test(void) {
+ dbgln("fseek TEST");
+ {
+#ifndef LINUX
+ FILE *fp = fopen("/testfile", "r");
+#else
+ FILE *fp = fopen("testfile", "r");
+#endif
+ assert(NULL != fp);
+ char c;
+ assert(0 == ftell(fp));
+ assert(1 == fread(&c, 1, 1, fp));
+ assert('A' == c);
+
+ assert(1 == ftell(fp));
+ assert(1 == fread(&c, 1, 1, fp));
+ assert('B' == c);
+
+ assert(2 == ftell(fp));
+ fseek(fp, 0, SEEK_SET);
+ assert(0 == ftell(fp));
+ assert(1 == fread(&c, 1, 1, fp));
+ assert('A' == c);
+ fseek(fp, 2, SEEK_SET);
+ assert(2 == ftell(fp));
+
+ assert(1 == fread(&c, 1, 1, fp));
+ assert('C' == c);
+ fseek(fp, 2, SEEK_CUR);
+ assert(5 == ftell(fp));
+ assert(1 == fread(&c, 1, 1, fp));
+ assert('F' == c);
+
+ char buffer[100];
+ assert(6 == ftell(fp));
+ fseek(fp, 0, SEEK_SET);
+ assert(1 == fread(buffer, 10, 1, fp));
+ assert(0 == memcmp(buffer, "ABCDEFGHIJK", 10));
+ assert(10 == ftell(fp));
+ fseek(fp, 1, SEEK_SET);
+ assert(10 == fread(buffer, 1, 10, fp));
+ assert(0 == memcmp(buffer, "BCDEFGHIJKL", 10));
+
+ fseek(fp, 0, SEEK_END);
+ assert(0 == fread(&c, 1, 1, fp));
+ fseek(fp, -2, SEEK_CUR);
+ assert(1 == fread(&c, 1, 1, fp));
+ assert('z' == c);
+ fseek(fp, -3, SEEK_END);
+ assert(1 == fread(&c, 1, 1, fp));
+ assert('y' == c);
+
+ assert(0 == fclose(fp));
+ }
+ dbgln("fseek TEST PASSED");
+}
+
+void printf_test(void) {
+#define EXP(exp) \
+ { \
+ int exp_n = strlen(exp); \
+ if (0 != strcmp(buf, exp) || buf_n != exp_n) { \
+ printf("buf n : %d\n", buf_n); \
+ printf("exp n : %d\n", snprintf(NULL, 0, "%s", exp)); \
+ printf("Expected: %s", exp); \
+ printf("\n"); \
+ printf("Got: %s", buf); \
+ printf("\n"); \
+ assert(0); \
+ } \
+ }
+ dbgln("printf TEST");
+ {
+ char buf[200];
+ int buf_n;
+ buf_n = sprintf(buf, "hello");
+ EXP("hello");
+ buf_n = sprintf(buf, "hello %s\n", "world");
+ EXP("hello world\n");
+ buf_n = sprintf(buf, "int: %d", 100);
+ EXP("int: 100");
+ buf_n = sprintf(buf, "int: %d, hex: %x, octal: %o a", 100, 100, 100);
+ EXP("int: 100, hex: 64, octal: 144 a");
+
+ buf_n = sprintf(buf, "int: %02d", 1);
+ EXP("int: 01");
+ buf_n = sprintf(buf, "int: %2d", 1);
+ EXP("int: 1");
+ buf_n = sprintf(buf, "int: %00d", 1);
+ EXP("int: 1");
+
+ buf_n = sprintf(buf, "hex: %02x", 1);
+ EXP("hex: 01");
+ buf_n = sprintf(buf, "hex: %2x", 1);
+ EXP("hex: 1");
+ buf_n = sprintf(buf, "hex: %00x", 1);
+ EXP("hex: 1");
+ buf_n = sprintf(buf, "hex: %x", 0x622933f2);
+ EXP("hex: 622933f2");
+
+ buf_n = sprintf(buf, "oct: %02o", 1);
+ EXP("oct: 01");
+ buf_n = sprintf(buf, "oct: %2o", 1);
+ EXP("oct: 1");
+ buf_n = sprintf(buf, "oct: %00o", 1);
+ EXP("oct: 1");
+
+ buf_n = sprintf(buf, "int: %-2dend", 1);
+ EXP("int: 1 end");
+ buf_n = sprintf(buf, "int: %-2dend", 12);
+ EXP("int: 12end");
+ buf_n = sprintf(buf, "int: %-0dend", 1);
+ EXP("int: 1end");
+
+ buf_n = sprintf(buf, "int: %-2xend", 1);
+ EXP("int: 1 end");
+ buf_n = sprintf(buf, "int: %-2xend", 12);
+ EXP("int: c end");
+ buf_n = sprintf(buf, "int: %-0xend", 1);
+ EXP("int: 1end");
+
+ buf_n = sprintf(buf, "int: %-2oend", 1);
+ EXP("int: 1 end");
+ buf_n = sprintf(buf, "int: %-2oend", 12);
+ EXP("int: 14end");
+ buf_n = sprintf(buf, "int: %-0oend", 1);
+ EXP("int: 1end");
+
+ buf_n = sprintf(buf, "string: %.3s", "foobar");
+ EXP("string: foo");
+ buf_n = sprintf(buf, "string: %.4s", "foobar");
+ EXP("string: foob");
+
+ buf_n = sprintf(buf, "string: %s\n", "ABCDEFGHIJKLMNOPQRSTUVXYZ");
+ EXP("string: ABCDEFGHIJKLMNOPQRSTUVXYZ\n");
+
+ buf_n = sprintf(buf, "string: %6send", "hello");
+ EXP("string: helloend");
+ buf_n = sprintf(buf, "string: %-6send", "hello");
+ EXP("string: hello end");
+ const char *data = "hello";
+ char *foo = "foo";
+ buf_n = sprintf(buf, " %-20s Legacy alias for \"%s\"\n", data, foo);
+ EXP(" hello Legacy alias for \"foo\"\n");
+ buf_n = sprintf(buf, " %-20s %s%s\n", data, foo, "bar");
+ EXP(" hello foobar\n");
+ // Make sure that parameters have not changed
+ assert(0 == strcmp(data, "hello"));
+ assert(0 == strcmp(foo, "foo"));
+
+ /* snprintf test */
+ char out_buffer[100];
+ memset(out_buffer, 'A', 100);
+ assert(5 == snprintf(out_buffer, 5, "hello"));
+ memcmp("helloAAAAA", out_buffer, 10);
+ assert(10 == snprintf(out_buffer, 5, "hellofoooo"));
+ memcmp("helloAAAAA", out_buffer, 10);
+ assert(10 == snprintf(out_buffer, 10, "hellofoooo"));
+ memcmp("hellofoookAA", out_buffer, 12);
+ }
+ dbgln("printf TEST PASSED");
+}
+
+int cmpfunc(const void *a, const void *b) { return (*(char *)a - *(char *)b); }
+
+void qsort_test(void) {
+ dbgln("qsort TEST");
+ {
+ char buf[] = {'B', 'D', 'C', 'A', '\0'};
+ qsort(buf, 4, sizeof(char), cmpfunc);
+ assert(0 == memcmp(buf, "ABCD", 4));
+ }
+ dbgln("qsort TEST PASSED");
+}
+
+void basename_test(void) {
+ dbgln("basename TEST");
+ {
+ char path[100];
+ const char *s;
+ strcpy(path, "/foo/bar");
+ s = basename(path);
+ assert(0 == strcmp(s, "bar"));
+
+ strcpy(path, "/foo/bar/");
+ s = basename(path);
+ assert(0 == strcmp(s, "bar"));
+
+ strcpy(path, "/");
+ s = basename(path);
+ assert(0 == strcmp(s, "/"));
+
+ strcpy(path, "//");
+ s = basename(path);
+ assert(0 == strcmp(s, "/"));
+
+ strcpy(path, "");
+ s = basename(path);
+ assert(0 == strcmp(s, "."));
+
+ s = basename(NULL);
+ assert(0 == strcmp(s, "."));
+ }
+ dbgln("basename TEST PASSED");
+}
+
+void dirname_test(void) {
+ dbgln("dirname TEST");
+ {
+ char path[100];
+ const char *s;
+ strcpy(path, "/foo/bar");
+ s = dirname(path);
+ assert(0 == strcmp(s, "foo"));
+
+ strcpy(path, "/foo/bar/");
+ s = dirname(path);
+ assert(0 == strcmp(s, "foo"));
+
+ strcpy(path, "/foo/bar/zoo");
+ s = dirname(path);
+ assert(0 == strcmp(s, "bar"));
+ }
+ dbgln("dirname TEST PASSED");
+}
+
+int main(void) {
+ dbgln("START");
+ malloc_test();
+ // json_test();
+ // random_test();
+ isx_test();
+ memcmp_test();
+ memcpy_test();
+ memmove_test();
+ strlen_test();
+ strnlen_test();
+ sscanf_test();
+ strtoul_test();
+ strcspn_test();
+ strpbrk_test();
+ strcpy_test();
+ strncpy_test();
+ strlcpy_test();
+ strcat_test();
+ strchr_test();
+ strrchr_test();
+ strdup_test();
+ strndup_test();
+ strspn_test();
+ strtol_test();
+ strcmp_test();
+ strncmp_test();
+ strcasecmp_test();
+ strncasecmp_test();
+ strstr_test();
+ strtok_test();
+ abs_test();
+ // fseek_test();
+ printf_test();
+ qsort_test();
+ basename_test();
+ dirname_test();
+ // TODO: Add mkstemp
+ return 0;
+}
diff --git a/userland/windowserver/Makefile b/userland/windowserver/Makefile
new file mode 100644
index 0000000..f67bd66
--- /dev/null
+++ b/userland/windowserver/Makefile
@@ -0,0 +1,16 @@
+CC="/home/anton/prj/osdev/sysroot/bin/i686-sb-gcc"
+CFLAGS = -ggdb -ffreestanding -O2 -Wall -Wextra -pedantic -mgeneral-regs-only -Wimplicit-fallthrough -fsanitize=shift,signed-integer-overflow,bounds
+BIN=ws
+LIB=-L../json -ljson -L../json/hashmap -lhashmap -L../libc -lc -lgcc
+INC=-I../json/ -I../libgui/
+all: $(BIN)
+OBJ=ws.o draw.o
+
+%.o: %.c
+ $(CC) $(CFLAGS) $(INC) $(LIB) -o $@ -c $<
+
+clean:
+ rm $(OBJ) ws
+
+$(BIN): $(OBJ)
+ $(CC) -o $(BIN) -ffreestanding -nostdlib $(CFLAGS) $(OBJ) $(LIB)
diff --git a/userland/windowserver/draw.c b/userland/windowserver/draw.c
new file mode 100644
index 0000000..caa16a2
--- /dev/null
+++ b/userland/windowserver/draw.c
@@ -0,0 +1,80 @@
+#include "draw.h"
+#include <string.h>
+
+#define BPP 4
+
+#define place_pixel(_p, _w, _h) \
+ { *(uint32_t *)(disp->back_buffer + BPP * (_w) + (WIDTH * BPP * (_h))) = _p; }
+
+#define place_pixel_pos(_p, _pos) \
+ { *(uint32_t *)(disp->back_buffer + BPP * (_pos)) = _p; }
+
+int mx;
+int my;
+
+void update_display(DISPLAY *disp) {
+ for (int i = 0; i < 20; i++) {
+ place_pixel(0xFFFFFFFF, mx + i, my + i);
+ place_pixel(0xFFFFFFFF, mx, my + i / 2);
+ place_pixel(0xFFFFFFFF, mx + i / 2, my);
+ }
+ for (int i = 0; i < disp->size; i++)
+ disp->true_buffer[i] = disp->back_buffer[i];
+ // memcpy(disp->true_buffer, disp->back_buffer, disp->size);
+}
+
+void draw_wallpaper(DISPLAY *disp) {
+ for (int i = 0; i < disp->size / BPP; i++) {
+ place_pixel_pos(0xFF00FF, i);
+ }
+}
+
+void draw_mouse(DISPLAY *disp, int mouse_x, int mouse_y) {
+ mx = mouse_x;
+ my = mouse_y;
+ update_full_display(disp, mouse_x, mouse_y);
+}
+
+void draw_window(DISPLAY *disp, const WINDOW *w) {
+ int x, y;
+ uint8_t border_size = disp->border_size;
+ const int px = w->x + border_size;
+ const int py = w->y;
+ const int sx = w->sx;
+ const int sy = w->sy;
+ x = px;
+ y = py;
+ for (int i = 0; i < sy; i++) {
+ if((i+py)*WIDTH + px > HEIGHT*WIDTH)
+ break;
+ uint32_t *ptr = disp->back_buffer + BPP * ((i + py) * WIDTH) + px * BPP;
+ if(i*sx > HEIGHT*WIDTH)
+ break;
+ uint32_t *bm = &w->bitmap_ptr[i * sx];
+ // ((uint8_t *)w->bitmap_ptr) + BPP * ((i + py) * WIDTH) + px * BPP;
+ for (int j = 0; j < sx; j++) {
+ ptr[j] = bm[j];
+ }
+ }
+}
+
+void update_active_window(DISPLAY *disp) {
+ for (int i = 0; i < 100; i++) {
+ if (!disp->clients[i])
+ continue;
+ if (!disp->clients[i]->w)
+ continue;
+ draw_window(disp, disp->clients[i]->w);
+ }
+}
+
+void update_full_display(DISPLAY *disp, int mouse_x, int mouse_y) {
+ draw_wallpaper(disp); /*
+ for (int i = 0; i < 100; i++) {
+ if (!disp->windows[i])
+ continue;
+ draw_window(disp, disp->windows[i]);
+ }*/
+ update_active_window(disp);
+ update_display(disp);
+}
diff --git a/userland/windowserver/draw.h b/userland/windowserver/draw.h
new file mode 100644
index 0000000..bf9ff4f
--- /dev/null
+++ b/userland/windowserver/draw.h
@@ -0,0 +1,13 @@
+#ifndef DRAW_H
+#define DRAW_H
+#include "ws.h"
+
+#define WIDTH 0x500
+#define HEIGHT 0x320
+
+void draw_wallpaper(DISPLAY *disp);
+void draw_window(DISPLAY *disp, const WINDOW *w);
+void update_full_display(DISPLAY *disp, int mouse_x, int mouse_y);
+void update_active_window(DISPLAY *disp);
+void draw_mouse(DISPLAY *disp, int mouse_x, int mouse_y);
+#endif
diff --git a/userland/windowserver/font.h b/userland/windowserver/font.h
new file mode 100644
index 0000000..ad63e41
--- /dev/null
+++ b/userland/windowserver/font.h
@@ -0,0 +1,133 @@
+#ifndef FONT_H
+#define FONT_H
+char font8x8_basic[128][8] = {
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0000 (nul)
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0001
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0002
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0003
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0004
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0005
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0006
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0007
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0008
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0009
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000A
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000B
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000C
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000D
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000E
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000F
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0010
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0011
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0012
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0013
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0014
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0015
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0016
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0017
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0018
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0019
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001A
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001B
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001C
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001D
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001E
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001F
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0020 (space)
+ { 0x18, 0x3C, 0x3C, 0x18, 0x18, 0x00, 0x18, 0x00}, // U+0021 (!)
+ { 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0022 (")
+ { 0x36, 0x36, 0x7F, 0x36, 0x7F, 0x36, 0x36, 0x00}, // U+0023 (#)
+ { 0x0C, 0x3E, 0x03, 0x1E, 0x30, 0x1F, 0x0C, 0x00}, // U+0024 ($)
+ { 0x00, 0x63, 0x33, 0x18, 0x0C, 0x66, 0x63, 0x00}, // U+0025 (%)
+ { 0x1C, 0x36, 0x1C, 0x6E, 0x3B, 0x33, 0x6E, 0x00}, // U+0026 (&)
+ { 0x06, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0027 (')
+ { 0x18, 0x0C, 0x06, 0x06, 0x06, 0x0C, 0x18, 0x00}, // U+0028 (()
+ { 0x06, 0x0C, 0x18, 0x18, 0x18, 0x0C, 0x06, 0x00}, // U+0029 ())
+ { 0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00}, // U+002A (*)
+ { 0x00, 0x0C, 0x0C, 0x3F, 0x0C, 0x0C, 0x00, 0x00}, // U+002B (+)
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x06}, // U+002C (,)
+ { 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00}, // U+002D (-)
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x00}, // U+002E (.)
+ { 0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x00}, // U+002F (/)
+ { 0x3E, 0x63, 0x73, 0x7B, 0x6F, 0x67, 0x3E, 0x00}, // U+0030 (0)
+ { 0x0C, 0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x3F, 0x00}, // U+0031 (1)
+ { 0x1E, 0x33, 0x30, 0x1C, 0x06, 0x33, 0x3F, 0x00}, // U+0032 (2)
+ { 0x1E, 0x33, 0x30, 0x1C, 0x30, 0x33, 0x1E, 0x00}, // U+0033 (3)
+ { 0x38, 0x3C, 0x36, 0x33, 0x7F, 0x30, 0x78, 0x00}, // U+0034 (4)
+ { 0x3F, 0x03, 0x1F, 0x30, 0x30, 0x33, 0x1E, 0x00}, // U+0035 (5)
+ { 0x1C, 0x06, 0x03, 0x1F, 0x33, 0x33, 0x1E, 0x00}, // U+0036 (6)
+ { 0x3F, 0x33, 0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x00}, // U+0037 (7)
+ { 0x1E, 0x33, 0x33, 0x1E, 0x33, 0x33, 0x1E, 0x00}, // U+0038 (8)
+ { 0x1E, 0x33, 0x33, 0x3E, 0x30, 0x18, 0x0E, 0x00}, // U+0039 (9)
+ { 0x00, 0x0C, 0x0C, 0x00, 0x00, 0x0C, 0x0C, 0x00}, // U+003A (:)
+ { 0x00, 0x0C, 0x0C, 0x00, 0x00, 0x0C, 0x0C, 0x06}, // U+003B (;)
+ { 0x18, 0x0C, 0x06, 0x03, 0x06, 0x0C, 0x18, 0x00}, // U+003C (<)
+ { 0x00, 0x00, 0x3F, 0x00, 0x00, 0x3F, 0x00, 0x00}, // U+003D (=)
+ { 0x06, 0x0C, 0x18, 0x30, 0x18, 0x0C, 0x06, 0x00}, // U+003E (>)
+ { 0x1E, 0x33, 0x30, 0x18, 0x0C, 0x00, 0x0C, 0x00}, // U+003F (?)
+ { 0x3E, 0x63, 0x7B, 0x7B, 0x7B, 0x03, 0x1E, 0x00}, // U+0040 (@)
+ { 0x0C, 0x1E, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x00}, // U+0041 (A)
+ { 0x3F, 0x66, 0x66, 0x3E, 0x66, 0x66, 0x3F, 0x00}, // U+0042 (B)
+ { 0x3C, 0x66, 0x03, 0x03, 0x03, 0x66, 0x3C, 0x00}, // U+0043 (C)
+ { 0x1F, 0x36, 0x66, 0x66, 0x66, 0x36, 0x1F, 0x00}, // U+0044 (D)
+ { 0x7F, 0x46, 0x16, 0x1E, 0x16, 0x46, 0x7F, 0x00}, // U+0045 (E)
+ { 0x7F, 0x46, 0x16, 0x1E, 0x16, 0x06, 0x0F, 0x00}, // U+0046 (F)
+ { 0x3C, 0x66, 0x03, 0x03, 0x73, 0x66, 0x7C, 0x00}, // U+0047 (G)
+ { 0x33, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x33, 0x00}, // U+0048 (H)
+ { 0x1E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+0049 (I)
+ { 0x78, 0x30, 0x30, 0x30, 0x33, 0x33, 0x1E, 0x00}, // U+004A (J)
+ { 0x67, 0x66, 0x36, 0x1E, 0x36, 0x66, 0x67, 0x00}, // U+004B (K)
+ { 0x0F, 0x06, 0x06, 0x06, 0x46, 0x66, 0x7F, 0x00}, // U+004C (L)
+ { 0x63, 0x77, 0x7F, 0x7F, 0x6B, 0x63, 0x63, 0x00}, // U+004D (M)
+ { 0x63, 0x67, 0x6F, 0x7B, 0x73, 0x63, 0x63, 0x00}, // U+004E (N)
+ { 0x1C, 0x36, 0x63, 0x63, 0x63, 0x36, 0x1C, 0x00}, // U+004F (O)
+ { 0x3F, 0x66, 0x66, 0x3E, 0x06, 0x06, 0x0F, 0x00}, // U+0050 (P)
+ { 0x1E, 0x33, 0x33, 0x33, 0x3B, 0x1E, 0x38, 0x00}, // U+0051 (Q)
+ { 0x3F, 0x66, 0x66, 0x3E, 0x36, 0x66, 0x67, 0x00}, // U+0052 (R)
+ { 0x1E, 0x33, 0x07, 0x0E, 0x38, 0x33, 0x1E, 0x00}, // U+0053 (S)
+ { 0x3F, 0x2D, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+0054 (T)
+ { 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x3F, 0x00}, // U+0055 (U)
+ { 0x33, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x00}, // U+0056 (V)
+ { 0x63, 0x63, 0x63, 0x6B, 0x7F, 0x77, 0x63, 0x00}, // U+0057 (W)
+ { 0x63, 0x63, 0x36, 0x1C, 0x1C, 0x36, 0x63, 0x00}, // U+0058 (X)
+ { 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x0C, 0x1E, 0x00}, // U+0059 (Y)
+ { 0x7F, 0x63, 0x31, 0x18, 0x4C, 0x66, 0x7F, 0x00}, // U+005A (Z)
+ { 0x1E, 0x06, 0x06, 0x06, 0x06, 0x06, 0x1E, 0x00}, // U+005B ([)
+ { 0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x40, 0x00}, // U+005C (\)
+ { 0x1E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1E, 0x00}, // U+005D (])
+ { 0x08, 0x1C, 0x36, 0x63, 0x00, 0x00, 0x00, 0x00}, // U+005E (^)
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF}, // U+005F (_)
+ { 0x0C, 0x0C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0060 (`)
+ { 0x00, 0x00, 0x1E, 0x30, 0x3E, 0x33, 0x6E, 0x00}, // U+0061 (a)
+ { 0x07, 0x06, 0x06, 0x3E, 0x66, 0x66, 0x3B, 0x00}, // U+0062 (b)
+ { 0x00, 0x00, 0x1E, 0x33, 0x03, 0x33, 0x1E, 0x00}, // U+0063 (c)
+ { 0x38, 0x30, 0x30, 0x3e, 0x33, 0x33, 0x6E, 0x00}, // U+0064 (d)
+ { 0x00, 0x00, 0x1E, 0x33, 0x3f, 0x03, 0x1E, 0x00}, // U+0065 (e)
+ { 0x1C, 0x36, 0x06, 0x0f, 0x06, 0x06, 0x0F, 0x00}, // U+0066 (f)
+ { 0x00, 0x00, 0x6E, 0x33, 0x33, 0x3E, 0x30, 0x1F}, // U+0067 (g)
+ { 0x07, 0x06, 0x36, 0x6E, 0x66, 0x66, 0x67, 0x00}, // U+0068 (h)
+ { 0x0C, 0x00, 0x0E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+0069 (i)
+ { 0x30, 0x00, 0x30, 0x30, 0x30, 0x33, 0x33, 0x1E}, // U+006A (j)
+ { 0x07, 0x06, 0x66, 0x36, 0x1E, 0x36, 0x67, 0x00}, // U+006B (k)
+ { 0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+006C (l)
+ { 0x00, 0x00, 0x33, 0x7F, 0x7F, 0x6B, 0x63, 0x00}, // U+006D (m)
+ { 0x00, 0x00, 0x1F, 0x33, 0x33, 0x33, 0x33, 0x00}, // U+006E (n)
+ { 0x00, 0x00, 0x1E, 0x33, 0x33, 0x33, 0x1E, 0x00}, // U+006F (o)
+ { 0x00, 0x00, 0x3B, 0x66, 0x66, 0x3E, 0x06, 0x0F}, // U+0070 (p)
+ { 0x00, 0x00, 0x6E, 0x33, 0x33, 0x3E, 0x30, 0x78}, // U+0071 (q)
+ { 0x00, 0x00, 0x3B, 0x6E, 0x66, 0x06, 0x0F, 0x00}, // U+0072 (r)
+ { 0x00, 0x00, 0x3E, 0x03, 0x1E, 0x30, 0x1F, 0x00}, // U+0073 (s)
+ { 0x08, 0x0C, 0x3E, 0x0C, 0x0C, 0x2C, 0x18, 0x00}, // U+0074 (t)
+ { 0x00, 0x00, 0x33, 0x33, 0x33, 0x33, 0x6E, 0x00}, // U+0075 (u)
+ { 0x00, 0x00, 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x00}, // U+0076 (v)
+ { 0x00, 0x00, 0x63, 0x6B, 0x7F, 0x7F, 0x36, 0x00}, // U+0077 (w)
+ { 0x00, 0x00, 0x63, 0x36, 0x1C, 0x36, 0x63, 0x00}, // U+0078 (x)
+ { 0x00, 0x00, 0x33, 0x33, 0x33, 0x3E, 0x30, 0x1F}, // U+0079 (y)
+ { 0x00, 0x00, 0x3F, 0x19, 0x0C, 0x26, 0x3F, 0x00}, // U+007A (z)
+ { 0x38, 0x0C, 0x0C, 0x07, 0x0C, 0x0C, 0x38, 0x00}, // U+007B ({)
+ { 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00}, // U+007C (|)
+ { 0x07, 0x0C, 0x0C, 0x38, 0x0C, 0x0C, 0x07, 0x00}, // U+007D (})
+ { 0x6E, 0x3B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+007E (~)
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} // U+007F
+};
+#endif
diff --git a/userland/windowserver/ws.c b/userland/windowserver/ws.c
new file mode 100644
index 0000000..e4f1a9e
--- /dev/null
+++ b/userland/windowserver/ws.c
@@ -0,0 +1,375 @@
+#include <fcntl.h>
+#include <poll.h>
+#include <stddef.h>
+#include <stdint.h>
+//#include <sys/mman.h>
+#include "draw.h"
+#include "font.h"
+#include "ws.h"
+#include <assert.h>
+#include <socket.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
+#define WINDOW_SERVER_SOCKET "/windowserver"
+
+CLIENT *clients[100];
+CLIENT *active_client;
+
+int mouse_x = 0;
+int mouse_y = 0;
+
+// void *true_display;
+// void *buffer_display;
+// uint64_t display_size;
+// int border_size;
+// uint8_t border_color;
+DISPLAY main_display;
+
+struct pollfd *fds;
+uint64_t num_fds;
+
+uint64_t socket_fd_poll;
+uint64_t keyboard_fd_poll;
+uint64_t mouse_fd_poll;
+
+// Taken from drivers/keyboard.c
+struct KEY_EVENT {
+ char c;
+ uint8_t mode; // (shift (0 bit)) (alt (1 bit))
+ uint8_t release; // 0 pressed, 1 released
+};
+
+int create_socket(void) {
+ struct sockaddr_un address;
+ int fd = socket(AF_UNIX, 0, 0);
+ address.sun_family = AF_UNIX;
+ size_t str_len = strlen(WINDOW_SERVER_SOCKET);
+ address.sun_path = malloc(str_len + 1);
+ memcpy(address.sun_path, WINDOW_SERVER_SOCKET, str_len);
+ address.sun_path[str_len] = 0;
+
+ bind(fd, (struct sockaddr *)(&address), sizeof(address));
+ // for(;;);
+ /*free(address.sun_path);*/
+ return fd;
+}
+
+void setup_display(DISPLAY *disp, const char *path, uint64_t size) {
+ disp->wallpaper_color = 0x3;
+ disp->size = size;
+ disp->vga_fd = open(path, O_RDWR, 0);
+ if (-1 == disp->vga_fd) {
+ perror("open");
+ for (;;)
+ ;
+ }
+ disp->true_buffer = mmap(NULL, size, 0, 0, disp->vga_fd, 0);
+ disp->back_buffer = malloc(size + 0x1000);
+ disp->clients = clients;
+}
+
+void setup(void) {
+ setup_display(&main_display, "/dev/vbe", 0xBB8000);
+ draw_wallpaper(&main_display);
+ update_display(&main_display);
+
+ main_display.border_size = 1;
+ main_display.border_color = 0xF;
+ active_client = NULL;
+ for (int i = 0; i < 100; i++) {
+ clients[i] = NULL;
+ }
+
+ num_fds = 100;
+ fds = malloc(sizeof(struct pollfd[num_fds]));
+ memset(fds, 0, sizeof(struct pollfd[num_fds]));
+ for (size_t i = 0; i < num_fds; i++)
+ fds[i].fd = -1;
+ // Create socket
+ int socket_fd = create_socket();
+ assert(socket_fd >= 0);
+ socket_fd_poll = 0;
+ fds[socket_fd_poll].fd = socket_fd;
+ fds[socket_fd_poll].events = POLLIN;
+ fds[socket_fd_poll].revents = 0;
+ int keyboard_fd = open("/dev/keyboard", O_RDONLY | O_NONBLOCK, 0);
+ assert(keyboard_fd >= 0);
+ keyboard_fd_poll = 1;
+ fds[keyboard_fd_poll].fd = keyboard_fd;
+ fds[keyboard_fd_poll].events = POLLIN;
+ fds[keyboard_fd_poll].revents = 0;
+ int mouse_fd = open("/dev/mouse", O_RDONLY, 0);
+ assert(mouse_fd >= 0);
+ mouse_fd_poll = 2;
+ fds[mouse_fd_poll].fd = mouse_fd;
+ fds[mouse_fd_poll].events = POLLIN;
+ fds[mouse_fd_poll].revents = 0;
+}
+
+void reset_revents(struct pollfd *fds, size_t s) {
+ for (size_t i = 0; i < s - 1; i++)
+ fds[i].revents = 0;
+}
+
+void add_fd(int fd) {
+ int i;
+ for (i = 0; i < num_fds; i++)
+ if (-1 == fds[i].fd)
+ break;
+
+ fds[i].fd = fd;
+ fds[i].events = POLLIN | POLLHUP;
+ // fds[i].events = POLLIN;
+ fds[i].revents = 0;
+}
+
+void add_client(int fd) {
+ int client_socket = accept(fd, NULL, NULL);
+ add_fd(client_socket);
+ int i;
+ for (i = 0; i < 100; i++)
+ if (!clients[i])
+ break;
+ printf("adding client: %d\n", i);
+ CLIENT *c = clients[i] = malloc(sizeof(CLIENT));
+ c->fd = client_socket;
+ active_client = c;
+ printf("clients[0]: %x\n", clients[0]);
+}
+
+#define CLIENT_EVENT_CREATESCREEN 0
+#define CLIENT_EVENT_UPDATESCREEN 1
+
+void add_window(CLIENT *c, int fd, int x, int y, int sx, int sy) {
+ WINDOW *w = malloc(sizeof(WINDOW));
+ w->bitmap_fd = fd;
+ w->bitmap_ptr = mmap(NULL, sx * sy * sizeof(uint32_t), 0, 0, fd, 0);
+ w->x = x;
+ w->y = y;
+ w->sx = sx;
+ w->sy = sy;
+ c->w = w;
+}
+
+typedef struct {
+ uint16_t px;
+ uint16_t py;
+ uint16_t sx;
+ uint16_t sy;
+ uint8_t name_len;
+} WS_EVENT_CREATE;
+
+void parse_client_event(CLIENT *c) {
+ uint8_t event_type;
+ if (0 == read(c->fd, &event_type, sizeof(uint8_t))) {
+ printf("empty\n");
+ return;
+ }
+ if (0 == event_type) {
+ update_full_display(&main_display, mouse_x, mouse_y);
+ return;
+ }
+ if (1 == event_type) {
+ WS_EVENT_CREATE e;
+ for (; 0 == read(c->fd, &e, sizeof(e));)
+ ;
+ uint8_t bitmap_name[e.name_len + 1];
+ read(c->fd, bitmap_name, e.name_len);
+ bitmap_name[e.name_len] = '\0';
+ int bitmap_fd = shm_open(bitmap_name, O_RDWR, O_CREAT);
+ add_window(c, bitmap_fd, e.px, e.py, e.sx, e.sy);
+ update_full_display(&main_display, mouse_x, mouse_y);
+ }
+}
+
+typedef struct {
+ int type;
+ struct KEY_EVENT ev;
+} WS_EVENT;
+
+void send_to_client(struct KEY_EVENT ev) {
+ WS_EVENT e = {
+ .type = 0,
+ .ev = ev,
+ };
+ write(active_client->fd, &e, sizeof(e));
+}
+
+void clamp_screen_position(int *x, int *y) {
+ if (0 > *x) {
+ *x = 0;
+ }
+ if (0 > *y) {
+ *y = 0;
+ }
+ if (WIDTH < *x) {
+ *x = WIDTH;
+ }
+ if (HEIGHT < *y) {
+ *y = HEIGHT;
+ }
+}
+
+int windowserver_key_events(struct KEY_EVENT ev, int *redraw) {
+ if (!(ev.mode & (1 << 1)))
+ return 0;
+ if (!active_client)
+ return 0;
+ int x = 0;
+ int y = 0;
+ switch (ev.c) {
+ case 'l':
+ x++;
+ break;
+ case 'h':
+ x--;
+ break;
+ case 'k':
+ y--;
+ break;
+ case 'j':
+ y++;
+ break;
+ }
+ if (x || y) {
+ active_client->w->x += x;
+ active_client->w->y += y;
+ clamp_screen_position(&active_client->w->x, &active_client->w->y);
+ *redraw = 1;
+ return 1;
+ }
+ return 0;
+}
+
+struct mouse_event {
+ uint8_t buttons;
+ uint8_t x;
+ uint8_t y;
+};
+
+void update_mouse(void) {
+ draw_mouse(&main_display, mouse_x, mouse_y);
+ return;
+}
+
+void parse_mouse_event(int fd) {
+ int16_t xc = 0;
+ int16_t yc = 0;
+ int middle_button = 0;
+ for (;;) {
+ struct mouse_event e[100];
+ int rc = read(fd, e, sizeof(e));
+ if (rc <= 0)
+ break;
+
+ int n = rc / sizeof(e[0]);
+ for (int i = 0; i < n; i++) {
+ uint8_t xs = e[i].buttons & (1 << 4);
+ uint8_t ys = e[i].buttons & (1 << 5);
+ middle_button = e[i].buttons & (1 << 2);
+ int16_t x = e[i].x;
+ int16_t y = e[i].y;
+ if (xs)
+ x |= 0xFF00;
+ if (ys)
+ y |= 0xFF00;
+ xc += *(int16_t *)&x;
+ yc += *(int16_t *)&y;
+ }
+ }
+ mouse_x += xc;
+ mouse_y -= yc;
+ if (mouse_x < 0)
+ mouse_x = 0;
+ if (mouse_y < 0)
+ mouse_y = 0;
+ if (middle_button) {
+ active_client->w->x += xc;
+ active_client->w->y -= yc;
+ clamp_screen_position(&active_client->w->x, &active_client->w->y);
+ }
+ update_mouse();
+}
+
+void parse_keyboard_event(int fd) {
+ if (!active_client) {
+ return;
+ }
+ struct KEY_EVENT ev[250];
+ int redraw = 0;
+ for (;;) {
+ int rc;
+ if (0 > (rc = read(fd, &ev[0], sizeof(ev))))
+ break;
+ int n = rc / sizeof(ev[0]);
+ for (int i = 0; i < n; i++) {
+ if (windowserver_key_events(ev[i], &redraw))
+ continue;
+ send_to_client(ev[i]);
+ }
+ }
+ if (redraw)
+ update_full_display(&main_display, mouse_x, mouse_y);
+}
+
+CLIENT *get_client(int fd) {
+ for (int i = 0; i < 100; i++) {
+ if (!clients[i])
+ continue;
+ if (clients[i]->fd == fd)
+ return clients[i];
+ }
+ return NULL;
+}
+
+void kill_client(CLIENT *c) {
+ c->w = NULL;
+ update_full_display(&main_display, mouse_x, mouse_y);
+ active_client = clients[0];
+}
+
+void parse_revents(struct pollfd *fds, size_t s) {
+ for (size_t i = 0; i < s - 1; i++) {
+ if (!fds[i].revents)
+ continue;
+ if (-1 == fds[i].fd)
+ continue;
+ if (socket_fd_poll == i && fds[i].revents & POLLIN) {
+ add_client(fds[i].fd);
+ continue;
+ } else if (keyboard_fd_poll == i) {
+ parse_keyboard_event(fds[i].fd);
+ continue;
+ } else if (mouse_fd_poll == i) {
+ parse_mouse_event(fds[i].fd);
+ continue;
+ }
+ CLIENT *c = get_client(fds[i].fd);
+ assert(c);
+ if (fds[i].revents & POLLHUP) {
+ kill_client(c);
+ fds[i].fd = -1;
+ } else {
+ parse_client_event(c);
+ }
+ }
+}
+
+void run(void) {
+ for (;;) {
+ poll(fds, num_fds, 0);
+ parse_revents(fds, num_fds);
+ reset_revents(fds, num_fds);
+ }
+}
+
+int main(void) {
+ open("/dev/serial", O_WRITE, 0);
+ open("/dev/serial", O_WRITE, 0);
+ setup();
+ run();
+ return 0;
+}
diff --git a/userland/windowserver/ws.h b/userland/windowserver/ws.h
new file mode 100644
index 0000000..c4daf7b
--- /dev/null
+++ b/userland/windowserver/ws.h
@@ -0,0 +1,30 @@
+#ifndef WS_H
+#define WS_H
+#include <stddef.h>
+#include <stdint.h>
+
+typedef struct {
+ int bitmap_fd;
+ uint32_t *bitmap_ptr;
+ int x;
+ int y;
+ int sx;
+ int sy;
+} WINDOW;
+
+typedef struct {
+ int fd;
+ WINDOW *w;
+} CLIENT;
+
+typedef struct {
+ int vga_fd;
+ uint8_t *back_buffer;
+ uint8_t *true_buffer;
+ size_t size;
+ uint8_t border_size;
+ uint8_t border_color;
+ uint8_t wallpaper_color;
+ CLIENT **clients;
+} DISPLAY;
+#endif