scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | Submodules | README | LICENSE

commit 687ff1f6ffd8929e0ccb55336225bb96292e8150
parent d9be6267deff0c8d91702a8a62ddf0dfb03ac713
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Tue,  4 Dec 2018 10:18:41 +0000

Big tree rework

Diffstat:
M.gitignore | 25++++---------------------
MMakefile | 34++++++++++++++++------------------
Dar/Makefile | 22----------------------
Dar/deps.mk | 7-------
Dar/main.c | 643-------------------------------------------------------------------------------
Das/Makefile | 29-----------------------------
Das/deps.mk | 46----------------------------------------------
Das/expr.c | 303-------------------------------------------------------------------------------
Das/gentbl.awk | 112-------------------------------------------------------------------------------
Das/gentbl.sh | 33---------------------------------
Das/ins.c | 249-------------------------------------------------------------------------------
Das/main.c | 138-------------------------------------------------------------------------------
Das/myro.c | 204-------------------------------------------------------------------------------
Das/parser.c | 482-------------------------------------------------------------------------------
Das/symbol.c | 291------------------------------------------------------------------------------
Das/target/amd64.mk | 8--------
Das/target/i286.mk | 8--------
Das/target/i386.mk | 8--------
Das/target/x80/ins.c | 600-------------------------------------------------------------------------------
Das/target/x80/z80.c | 64----------------------------------------------------------------
Das/target/x86/amd64.c | 12------------
Das/target/x86/i286.c | 53-----------------------------------------------------
Das/target/x86/i386.c | 100-------------------------------------------------------------------------------
Das/target/x86/ins.c | 301-------------------------------------------------------------------------------
Das/target/z80.mk | 8--------
Dcc1/Makefile | 32--------------------------------
Dcc1/builtin.c | 121-------------------------------------------------------------------------------
Dcc1/code.c | 550-------------------------------------------------------------------------------
Dcc1/cpp.c | 839-------------------------------------------------------------------------------
Dcc1/decl.c | 967-------------------------------------------------------------------------------
Dcc1/deps.mk | 45---------------------------------------------
Dcc1/error.c | 85-------------------------------------------------------------------------------
Dcc1/expr.c | 1185-------------------------------------------------------------------------------
Dcc1/fold.c | 685-------------------------------------------------------------------------------
Dcc1/init.c | 378-------------------------------------------------------------------------------
Dcc1/lex.c | 801-------------------------------------------------------------------------------
Dcc1/main.c | 102-------------------------------------------------------------------------------
Dcc1/stmt.c | 386-------------------------------------------------------------------------------
Dcc1/symbol.c | 353-------------------------------------------------------------------------------
Dcc1/target/amd64-sysv/arch.c | 220-------------------------------------------------------------------------------
Dcc1/target/amd64-sysv/arch.mk | 5-----
Dcc1/target/arm64-sysv/arch.c | 220-------------------------------------------------------------------------------
Dcc1/target/arm64-sysv/arch.mk | 5-----
Dcc1/target/i386-sysv/arch.c | 221-------------------------------------------------------------------------------
Dcc1/target/i386-sysv/arch.mk | 5-----
Dcc1/target/z80-scc/arch.c | 219-------------------------------------------------------------------------------
Dcc1/target/z80-scc/arch.mk | 5-----
Dcc1/types.c | 438-------------------------------------------------------------------------------
Dcc2/Makefile | 35-----------------------------------
Dcc2/code.c | 133-------------------------------------------------------------------------------
Dcc2/deps.mk | 61-------------------------------------------------------------
Dcc2/main.c | 70----------------------------------------------------------------------
Dcc2/node.c | 142-------------------------------------------------------------------------------
Dcc2/optm.c | 9---------
Dcc2/parser.c | 722-------------------------------------------------------------------------------
Dcc2/peep.c | 8--------
Dcc2/symbol.c | 92-------------------------------------------------------------------------------
Dcc2/target/amd64-sysv/cgen.c | 15---------------
Dcc2/target/amd64-sysv/code.c | 210-------------------------------------------------------------------------------
Dcc2/target/amd64-sysv/optm.c | 10----------
Dcc2/target/amd64-sysv/target.mk | 9---------
Dcc2/target/amd64-sysv/types.c | 93-------------------------------------------------------------------------------
Dcc2/target/i386-sysv/cgen.c | 15---------------
Dcc2/target/i386-sysv/code.c | 208-------------------------------------------------------------------------------
Dcc2/target/i386-sysv/optm.c | 10----------
Dcc2/target/i386-sysv/target.mk | 9---------
Dcc2/target/i386-sysv/types.c | 94-------------------------------------------------------------------------------
Dcc2/target/qbe/cgen.c | 728-------------------------------------------------------------------------------
Dcc2/target/qbe/code.c | 568-------------------------------------------------------------------------------
Dcc2/target/qbe/optm.c | 57---------------------------------------------------------
Dcc2/target/qbe_amd64-sysv/target.mk | 9---------
Dcc2/target/qbe_arm64-sysv/target.mk | 5-----
Dcc2/target/z80-scc/cgen.c | 160-------------------------------------------------------------------------------
Dcc2/target/z80-scc/code.c | 228-------------------------------------------------------------------------------
Dcc2/target/z80-scc/optm.c | 10----------
Dcc2/target/z80-scc/target.mk | 9---------
Dcc2/target/z80-scc/types.c | 94-------------------------------------------------------------------------------
Dconfig.mk | 30------------------------------
Dconfig.sh | 16----------------
Aconfig/amd64-linux.mk | 8++++++++
Aconfig/i386-linux.mk | 5+++++
Ddriver/Makefile | 10----------
Ddriver/posix/Makefile | 42------------------------------------------
Dinc/Makefile | 37-------------------------------------
Dinc/incdep.mk | 7-------
Dinc/inclst.mk | 4----
Ainclude/assert.h | 8++++++++
Ainclude/bits/.gitignore | 1+
Ainclude/bits/amd64/arch/limits.h | 18++++++++++++++++++
Ainclude/bits/amd64/arch/setjmp.h | 1+
Ainclude/bits/amd64/arch/stddef.h | 14++++++++++++++
Ainclude/bits/amd64/arch/stdint.h | 102+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ainclude/bits/amd64/arch/stdio.h | 15+++++++++++++++
Ainclude/bits/amd64/arch/stdlib.h | 14++++++++++++++
Ainclude/bits/amd64/arch/string.h | 6++++++
Ainclude/bits/amd64/arch/time.h | 8++++++++
Ainclude/bits/arm32/arch/limits.h | 18++++++++++++++++++
Ainclude/bits/arm32/arch/setjmp.h | 1+
Ainclude/bits/arm32/arch/stddef.h | 9+++++++++
Ainclude/bits/arm32/arch/stdint.h | 96+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ainclude/bits/arm32/arch/stdio.h | 15+++++++++++++++
Ainclude/bits/arm32/arch/stdlib.h | 14++++++++++++++
Ainclude/bits/arm32/arch/string.h | 6++++++
Ainclude/bits/arm32/arch/time.h | 8++++++++
Ainclude/bits/arm64/arch/limits.h | 18++++++++++++++++++
Ainclude/bits/arm64/arch/setjmp.h | 1+
Ainclude/bits/arm64/arch/stddef.h | 9+++++++++
Ainclude/bits/arm64/arch/stdint.h | 96+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ainclude/bits/arm64/arch/stdio.h | 15+++++++++++++++
Ainclude/bits/arm64/arch/stdlib.h | 14++++++++++++++
Ainclude/bits/arm64/arch/string.h | 6++++++
Ainclude/bits/arm64/arch/time.h | 8++++++++
Ainclude/bits/dragonfly/sys.h | 19+++++++++++++++++++
Ainclude/bits/dragonfly/sys/signal.h | 27+++++++++++++++++++++++++++
Ainclude/bits/i386/arch/limits.h | 18++++++++++++++++++
Ainclude/bits/i386/arch/stddef.h | 14++++++++++++++
Ainclude/bits/i386/arch/stdint.h | 115+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ainclude/bits/i386/arch/stdio.h | 15+++++++++++++++
Ainclude/bits/i386/arch/stdlib.h | 14++++++++++++++
Ainclude/bits/i386/arch/string.h | 5+++++
Ainclude/bits/i386/arch/time.h | 8++++++++
Ainclude/bits/linux/sys.h | 19+++++++++++++++++++
Ainclude/bits/linux/sys/signal.h | 27+++++++++++++++++++++++++++
Ainclude/bits/netbsd/sys.h | 19+++++++++++++++++++
Ainclude/bits/netbsd/sys/signal.h | 27+++++++++++++++++++++++++++
Ainclude/bits/openbsd/sys.h | 19+++++++++++++++++++
Ainclude/bits/openbsd/sys/signal.h | 27+++++++++++++++++++++++++++
Ainclude/bits/z80/arch/limits.h | 18++++++++++++++++++
Ainclude/bits/z80/arch/stddef.h | 14++++++++++++++
Ainclude/bits/z80/arch/stdint.h | 115+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ainclude/bits/z80/arch/stdio.h | 15+++++++++++++++
Ainclude/bits/z80/arch/stdlib.h | 14++++++++++++++
Ainclude/bits/z80/arch/string.h | 5+++++
Ainclude/bits/z80/arch/time.h | 8++++++++
Ainclude/ctype.h | 45+++++++++++++++++++++++++++++++++++++++++++++
Ainclude/errno.h | 6++++++
Ainclude/float.h | 1+
Ainclude/limits.h | 8++++++++
Ainclude/locale.h | 39+++++++++++++++++++++++++++++++++++++++
Ainclude/math.h | 4++++
Ainclude/scc/scc/.gitignore | 5+++++
Ainclude/scc/scc/Makefile | 42++++++++++++++++++++++++++++++++++++++++++
Rinc/ar.h -> include/scc/scc/ar.h | 0
Rinc/arg.h -> include/scc/scc/arg.h | 0
Rinc/coff32/aouthdr.h -> include/scc/scc/coff32/aouthdr.h | 0
Rinc/coff32/coff32.h -> include/scc/scc/coff32/coff32.h | 0
Rinc/coff32/filehdr.h -> include/scc/scc/coff32/filehdr.h | 0
Rinc/coff32/linenum.h -> include/scc/scc/coff32/linenum.h | 0
Rinc/coff32/reloc.h -> include/scc/scc/coff32/reloc.h | 0
Rinc/coff32/scnhdr.h -> include/scc/scc/coff32/scnhdr.h | 0
Rinc/coff32/syms.h -> include/scc/scc/coff32/syms.h | 0
Rinc/c89/cstd.h -> include/scc/scc/cstd-c89.h | 0
Rinc/c99/cstd.h -> include/scc/scc/cstd-c99.h | 0
Rinc/ldflags.def.h -> include/scc/scc/ldflags.def.h | 0
Rinc/myro.h -> include/scc/scc/myro.h | 0
Rinc/scc.h -> include/scc/scc/scc.h | 0
Rinc/syscrts.def.h -> include/scc/scc/syscrts.def.h | 0
Rinc/sysincludes.def.h -> include/scc/scc/sysincludes.def.h | 0
Rinc/syslibs.def.h -> include/scc/scc/syslibs.def.h | 0
Ainclude/setjmp.h | 11+++++++++++
Ainclude/signal.h | 9+++++++++
Ainclude/stdarg.h | 10++++++++++
Ainclude/stdbool.h | 9+++++++++
Ainclude/stddef.h | 12++++++++++++
Ainclude/stdint.h | 6++++++
Ainclude/stdio.h | 123+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ainclude/stdlib.h | 69+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ainclude/string.h | 34++++++++++++++++++++++++++++++++++
Ainclude/time.h | 43+++++++++++++++++++++++++++++++++++++++++++
Ainclude/wchar.h | 92+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ainclude/wctype.h | 30++++++++++++++++++++++++++++++
Dld/Makefile | 23-----------------------
Dld/coff32.c | 403-------------------------------------------------------------------------------
Dld/deps.mk | 15---------------
Dld/main.c | 288-------------------------------------------------------------------------------
Dld/obj.c | 153-------------------------------------------------------------------------------
Dlib/Makefile | 15---------------
Dlib/c/Makefile | 29-----------------------------
Dlib/c/arch/arm32/linux/time.c | 1-
Dlib/c/arch/arm32/longjmp.s | 11-----------
Dlib/c/arch/arm32/setjmp.s | 9---------
Dlib/c/arch/arm64/Makefile | 14--------------
Dlib/c/arch/arm64/linux/.gitignore | 10----------
Dlib/c/arch/arm64/linux/Makefile | 37-------------------------------------
Dlib/c/arch/arm64/linux/_cerrno.s | 13-------------
Dlib/c/arch/arm64/linux/_getheap.s | 6------
Dlib/c/arch/arm64/linux/_open.c | 13-------------
Dlib/c/arch/arm64/linux/_sigaction.c | 14--------------
Dlib/c/arch/arm64/linux/_tzone.c | 1-
Dlib/c/arch/arm64/linux/gensys.sh | 21---------------------
Dlib/c/arch/arm64/linux/getenv.c | 1-
Dlib/c/arch/arm64/linux/raise.c | 1-
Dlib/c/arch/arm64/linux/signal.c | 1-
Dlib/c/arch/arm64/linux/syscall.lst | 11-----------
Dlib/c/arch/arm64/linux/time.c | 1-
Dlib/c/arch/arm64/longjmp.s | 22----------------------
Dlib/c/arch/arm64/setjmp.s | 20--------------------
Dlib/c/arch/generrno.sh | 35-----------------------------------
Dlib/c/arch/generrstr.sh | 23-----------------------
Dlib/c/arch/mkerrstr | 24------------------------
Dlib/c/arch/posix/_tzone.c | 27---------------------------
Dlib/c/arch/posix/getenv.c | 18------------------
Dlib/c/arch/posix/geterrno.sh | 8--------
Dlib/c/arch/posix/raise.c | 11-----------
Dlib/c/arch/posix/signal.c | 17-----------------
Dlib/c/arch/posix/time.c | 21---------------------
Dlib/c/arch/rules.mk | 4----
Dlib/c/assert/Makefile | 10----------
Dlib/c/assert/__assert.c | 9---------
Dlib/c/assert/assert.c | 13-------------
Dlib/c/ctype/Makefile | 24------------------------
Dlib/c/ctype/ctype.c | 22----------------------
Dlib/c/ctype/isalnum.c | 8--------
Dlib/c/ctype/isalpha.c | 8--------
Dlib/c/ctype/isascii.c | 8--------
Dlib/c/ctype/isblank.c | 7-------
Dlib/c/ctype/iscntrl.c | 8--------
Dlib/c/ctype/isdigit.c | 8--------
Dlib/c/ctype/isgraph.c | 8--------
Dlib/c/ctype/islower.c | 8--------
Dlib/c/ctype/isprint.c | 8--------
Dlib/c/ctype/ispunct.c | 8--------
Dlib/c/ctype/isspace.c | 8--------
Dlib/c/ctype/isupper.c | 8--------
Dlib/c/ctype/isxdigit.c | 8--------
Dlib/c/ctype/tolower.c | 9---------
Dlib/c/ctype/toupper.c | 8--------
Dlib/c/libc.h | 42------------------------------------------
Dlib/c/locale/Makefile | 10----------
Dlib/c/locale/localeconv.c | 29-----------------------------
Dlib/c/locale/setlocale.c | 16----------------
Dlib/c/mklst | 12------------
Dlib/c/stdio/Makefile | 47-----------------------------------------------
Dlib/c/stdio/__getc.c | 39---------------------------------------
Dlib/c/stdio/__iob.c | 20--------------------
Dlib/c/stdio/__putc.c | 78------------------------------------------------------------------------------
Dlib/c/stdio/_allocbuf.c | 21---------------------
Dlib/c/stdio/_flsbuf.c | 23-----------------------
Dlib/c/stdio/_fpopen.c | 75---------------------------------------------------------------------------
Dlib/c/stdio/clearerr.c | 8--------
Dlib/c/stdio/fclose.c | 32--------------------------------
Dlib/c/stdio/feof.c | 8--------
Dlib/c/stdio/ferror.c | 8--------
Dlib/c/stdio/fgetc.c | 8--------
Dlib/c/stdio/fgets.c | 19-------------------
Dlib/c/stdio/fopen.c | 23-----------------------
Dlib/c/stdio/fprintf.c | 15---------------
Dlib/c/stdio/fputc.c | 8--------
Dlib/c/stdio/fputs.c | 12------------
Dlib/c/stdio/fread.c | 25-------------------------
Dlib/c/stdio/freopen.c | 14--------------
Dlib/c/stdio/fseek.c | 26--------------------------
Dlib/c/stdio/ftell.c | 27---------------------------
Dlib/c/stdio/fwrite.c | 24------------------------
Dlib/c/stdio/getc.c | 8--------
Dlib/c/stdio/getchar.c | 8--------
Dlib/c/stdio/gets.c | 17-----------------
Dlib/c/stdio/perror.c | 16----------------
Dlib/c/stdio/printf.c | 15---------------
Dlib/c/stdio/putc.c | 8--------
Dlib/c/stdio/putchar.c | 8--------
Dlib/c/stdio/puts.c | 12------------
Dlib/c/stdio/rewind.c | 10----------
Dlib/c/stdio/setbuf.c | 8--------
Dlib/c/stdio/setvbuf.c | 48------------------------------------------------
Dlib/c/stdio/snprintf.c | 16----------------
Dlib/c/stdio/sprintf.c | 16----------------
Dlib/c/stdio/tmpnam.c | 31-------------------------------
Dlib/c/stdio/vfprintf.c | 362-------------------------------------------------------------------------------
Dlib/c/stdio/vprintf.c | 12------------
Dlib/c/stdio/vsnprintf.c | 25-------------------------
Dlib/c/stdio/vsprintf.c | 12------------
Dlib/c/stdlib/Makefile | 25-------------------------
Dlib/c/stdlib/abort.c | 10----------
Dlib/c/stdlib/abs.c | 8--------
Dlib/c/stdlib/atexit.c | 17-----------------
Dlib/c/stdlib/atoi.c | 25-------------------------
Dlib/c/stdlib/atol.c | 26--------------------------
Dlib/c/stdlib/atoll.c | 26--------------------------
Dlib/c/stdlib/bsearch.c | 26--------------------------
Dlib/c/stdlib/calloc.c | 18------------------
Dlib/c/stdlib/errno.c | 1-
Dlib/c/stdlib/exit.c | 13-------------
Dlib/c/stdlib/labs.c | 8--------
Dlib/c/stdlib/llabs.c | 8--------
Dlib/c/stdlib/malloc.c | 158-------------------------------------------------------------------------------
Dlib/c/stdlib/malloc.h | 16----------------
Dlib/c/stdlib/qsort.c | 68--------------------------------------------------------------------
Dlib/c/stdlib/rand.c | 18------------------
Dlib/c/stdlib/realloc.c | 68--------------------------------------------------------------------
Dlib/c/stdlib/strtoull.c | 64----------------------------------------------------------------
Dlib/c/string/Makefile | 31-------------------------------
Dlib/c/string/memchr.c | 12------------
Dlib/c/string/memcmp.c | 14--------------
Dlib/c/string/memcpy.c | 13-------------
Dlib/c/string/memmove.c | 18------------------
Dlib/c/string/memset.c | 12------------
Dlib/c/string/strcat.c | 14--------------
Dlib/c/string/strchr.c | 10----------
Dlib/c/string/strcmp.c | 10----------
Dlib/c/string/strcoll.c | 10----------
Dlib/c/string/strcpy.c | 12------------
Dlib/c/string/strcspn.c | 21---------------------
Dlib/c/string/strerror.c | 11-----------
Dlib/c/string/strlen.c | 12------------
Dlib/c/string/strncat.c | 15---------------
Dlib/c/string/strncmp.c | 14--------------
Dlib/c/string/strncpy.c | 14--------------
Dlib/c/string/strnlen.c | 13-------------
Dlib/c/string/strpbrk.c | 20--------------------
Dlib/c/string/strrchr.c | 14--------------
Dlib/c/string/strspn.c | 21---------------------
Dlib/c/string/strstr.c | 18------------------
Dlib/c/string/strtok.c | 25-------------------------
Dlib/c/string/strxfrm.c | 12------------
Dlib/c/syscall.h | 8--------
Dlib/c/time/Makefile | 16----------------
Dlib/c/time/_daysyear.c | 30------------------------------
Dlib/c/time/asctime.c | 12------------
Dlib/c/time/ctime.c | 8--------
Dlib/c/time/difftime.c | 8--------
Dlib/c/time/gmtime.c | 35-----------------------------------
Dlib/c/time/localtime.c | 21---------------------
Dlib/c/time/mktime.c | 112-------------------------------------------------------------------------------
Dlib/c/time/strftime.c | 246-------------------------------------------------------------------------------
Dlib/coff32/Makefile | 22----------------------
Dlib/coff32/coff32_pack_aout.c | 9---------
Dlib/coff32/coff32_pack_ent.c | 20--------------------
Dlib/coff32/coff32_pack_hdr.c | 21---------------------
Dlib/coff32/coff32_pack_scn.c | 24------------------------
Dlib/coff32/coff32_unpack_aout.c | 9---------
Dlib/coff32/coff32_unpack_ent.c | 20--------------------
Dlib/coff32/coff32_unpack_hdr.c | 22----------------------
Dlib/coff32/coff32_unpack_scn.c | 24------------------------
Dlib/coff32/deps.mk | 17-----------------
Dlib/coff32/libdep.mk | 4----
Dlib/coff32/objlst.mk | 9---------
Dlib/crt/Makefile | 14--------------
Dlib/crt/amd64-sysv-linux/Makefile | 9---------
Dlib/crt/amd64-sysv-linux/crt.s | 8--------
Dlib/crt/amd64-sysv-netbsd/Makefile | 9---------
Dlib/crt/amd64-sysv-netbsd/crt.s | 30------------------------------
Dlib/crt/amd64-sysv-openbsd/Makefile | 9---------
Dlib/crt/amd64-sysv-openbsd/crt.s | 18------------------
Dlib/crt/common.mk | 8--------
Dlib/crt/i386-sysv-linux/crt.s | 1-
Dlib/crt/i386-sysv-openbsd/crt.s | 1-
Dlib/crt/z80-scc-none/crt.s | 8--------
Dlib/scc/Makefile | 21---------------------
Dlib/scc/alloc.c | 112-------------------------------------------------------------------------------
Dlib/scc/bpack.c | 64----------------------------------------------------------------
Dlib/scc/bunpack.c | 71-----------------------------------------------------------------------
Dlib/scc/casecmp.c | 11-----------
Dlib/scc/debug.c | 20--------------------
Dlib/scc/deps.mk | 18------------------
Dlib/scc/die.c | 20--------------------
Dlib/scc/libdep.mk | 4----
Dlib/scc/lpack.c | 64----------------------------------------------------------------
Dlib/scc/lunpack.c | 71-----------------------------------------------------------------------
Dlib/scc/newitem.c | 12------------
Dlib/scc/objlst.mk | 16----------------
Dlib/scc/rmyro.c | 94-------------------------------------------------------------------------------
Dlib/scc/wmyro.c | 86-------------------------------------------------------------------------------
Dlib/scc/xcalloc.c | 13-------------
Dlib/scc/xmalloc.c | 13-------------
Dlib/scc/xrealloc.c | 13-------------
Dlib/scc/xstrdup.c | 12------------
Dmkdep.sh | 19-------------------
Dnm/Makefile | 22----------------------
Dnm/coff32.c | 312-------------------------------------------------------------------------------
Dnm/deps.mk | 12------------
Dnm/formats.c | 13-------------
Dnm/main.c | 272-------------------------------------------------------------------------------
Dnm/nm.h | 14--------------
Dobjdump/Makefile | 20--------------------
Dobjdump/deps.mk | 4----
Dobjdump/main.c | 333-------------------------------------------------------------------------------
Droot/bin/README | 1-
Droot/include/scc/assert.h | 8--------
Droot/include/scc/bits/.gitignore | 1-
Droot/include/scc/bits/amd64/arch/limits.h | 18------------------
Droot/include/scc/bits/amd64/arch/setjmp.h | 1-
Droot/include/scc/bits/amd64/arch/stddef.h | 14--------------
Droot/include/scc/bits/amd64/arch/stdint.h | 102-------------------------------------------------------------------------------
Droot/include/scc/bits/amd64/arch/stdio.h | 15---------------
Droot/include/scc/bits/amd64/arch/stdlib.h | 14--------------
Droot/include/scc/bits/amd64/arch/string.h | 6------
Droot/include/scc/bits/amd64/arch/time.h | 8--------
Droot/include/scc/bits/arm32/arch/limits.h | 18------------------
Droot/include/scc/bits/arm32/arch/setjmp.h | 1-
Droot/include/scc/bits/arm32/arch/stddef.h | 9---------
Droot/include/scc/bits/arm32/arch/stdint.h | 96-------------------------------------------------------------------------------
Droot/include/scc/bits/arm32/arch/stdio.h | 15---------------
Droot/include/scc/bits/arm32/arch/stdlib.h | 14--------------
Droot/include/scc/bits/arm32/arch/string.h | 6------
Droot/include/scc/bits/arm32/arch/time.h | 8--------
Droot/include/scc/bits/arm64/arch/limits.h | 18------------------
Droot/include/scc/bits/arm64/arch/setjmp.h | 1-
Droot/include/scc/bits/arm64/arch/stddef.h | 9---------
Droot/include/scc/bits/arm64/arch/stdint.h | 96-------------------------------------------------------------------------------
Droot/include/scc/bits/arm64/arch/stdio.h | 15---------------
Droot/include/scc/bits/arm64/arch/stdlib.h | 14--------------
Droot/include/scc/bits/arm64/arch/string.h | 6------
Droot/include/scc/bits/arm64/arch/time.h | 8--------
Droot/include/scc/bits/dragonfly/sys.h | 19-------------------
Droot/include/scc/bits/dragonfly/sys/signal.h | 27---------------------------
Droot/include/scc/bits/i386/arch/limits.h | 18------------------
Droot/include/scc/bits/i386/arch/stddef.h | 14--------------
Droot/include/scc/bits/i386/arch/stdint.h | 115-------------------------------------------------------------------------------
Droot/include/scc/bits/i386/arch/stdio.h | 15---------------
Droot/include/scc/bits/i386/arch/stdlib.h | 14--------------
Droot/include/scc/bits/i386/arch/string.h | 5-----
Droot/include/scc/bits/i386/arch/time.h | 8--------
Droot/include/scc/bits/linux/sys.h | 19-------------------
Droot/include/scc/bits/linux/sys/signal.h | 27---------------------------
Droot/include/scc/bits/netbsd/sys.h | 19-------------------
Droot/include/scc/bits/netbsd/sys/signal.h | 27---------------------------
Droot/include/scc/bits/openbsd/sys.h | 19-------------------
Droot/include/scc/bits/openbsd/sys/signal.h | 27---------------------------
Droot/include/scc/bits/z80/arch/limits.h | 18------------------
Droot/include/scc/bits/z80/arch/stddef.h | 14--------------
Droot/include/scc/bits/z80/arch/stdint.h | 115-------------------------------------------------------------------------------
Droot/include/scc/bits/z80/arch/stdio.h | 15---------------
Droot/include/scc/bits/z80/arch/stdlib.h | 14--------------
Droot/include/scc/bits/z80/arch/string.h | 5-----
Droot/include/scc/bits/z80/arch/time.h | 8--------
Droot/include/scc/ctype.h | 45---------------------------------------------
Droot/include/scc/errno.h | 6------
Droot/include/scc/float.h | 1-
Droot/include/scc/limits.h | 8--------
Droot/include/scc/locale.h | 39---------------------------------------
Droot/include/scc/math.h | 4----
Droot/include/scc/setjmp.h | 11-----------
Droot/include/scc/signal.h | 9---------
Droot/include/scc/stdarg.h | 10----------
Droot/include/scc/stdbool.h | 9---------
Droot/include/scc/stddef.h | 12------------
Droot/include/scc/stdint.h | 6------
Droot/include/scc/stdio.h | 123-------------------------------------------------------------------------------
Droot/include/scc/stdlib.h | 69---------------------------------------------------------------------
Droot/include/scc/string.h | 34----------------------------------
Droot/include/scc/time.h | 43-------------------------------------------
Droot/include/scc/wchar.h | 92-------------------------------------------------------------------------------
Droot/include/scc/wctype.h | 30------------------------------
Droot/lib/scc/amd64-sysv-linux/README | 1-
Droot/lib/scc/amd64-sysv-netbsd/README | 1-
Droot/lib/scc/amd64-sysv-openbsd/README | 1-
Droot/lib/scc/i386-sysv-linux/README | 1-
Droot/lib/scc/i386-sysv-openbsd/README | 1-
Droot/lib/scc/z80-scc-none/README | 1-
Droot/libexec/scc/README | 1-
Drules.mk | 37-------------------------------------
Ascripts/libc-proto | 10++++++++++
Ascripts/mkdep | 22++++++++++++++++++++++
Ascripts/rules.mk | 52++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/Makefile | 20++++++++++++++++++++
Asrc/ar/Makefile | 22++++++++++++++++++++++
Asrc/ar/deps.mk | 5+++++
Asrc/ar/main.c | 643+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Rar/posix/driver.c -> src/ar/posix/driver.c | 0
Rar/posix/driver.h -> src/ar/posix/driver.h | 0
Asrc/as/Makefile | 33+++++++++++++++++++++++++++++++++
Ras/as.h -> src/as/as.h | 0
Asrc/as/deps.mk | 33+++++++++++++++++++++++++++++++++
Asrc/as/expr.c | 303+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/as/ins.c | 249+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/as/main.c | 138+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/as/mktbl | 32++++++++++++++++++++++++++++++++
Asrc/as/mktbl.awk | 112+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/as/myro.c | 204+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/as/parser.c | 482+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/as/symbol.c | 291++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/as/target/amd64.mk | 10++++++++++
Asrc/as/target/i286.mk | 10++++++++++
Asrc/as/target/i386.mk | 10++++++++++
Asrc/as/target/x80/.gitignore | 1+
Asrc/as/target/x80/ins.c | 601+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ras/target/x80/proc.h -> src/as/target/x80/proc.h | 0
Ras/target/x80/rules.dat -> src/as/target/x80/rules.dat | 0
Ras/target/x80/x80.dat -> src/as/target/x80/x80.dat | 0
Asrc/as/target/x80/z80.c | 65+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/as/target/x86/.gitignore | 3+++
Asrc/as/target/x86/amd64.c | 13+++++++++++++
Asrc/as/target/x86/i286.c | 54++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/as/target/x86/i386.c | 101+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/as/target/x86/ins.c | 302++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ras/target/x86/nasm.dat -> src/as/target/x86/nasm.dat | 0
Ras/target/x86/proc.h -> src/as/target/x86/proc.h | 0
Ras/target/x86/rules.dat -> src/as/target/x86/rules.dat | 0
Ras/target/x86/x86.dat -> src/as/target/x86/x86.dat | 0
Asrc/as/target/z80.mk | 10++++++++++
Asrc/cc1/Makefile | 38++++++++++++++++++++++++++++++++++++++
Rcc1/TODO -> src/cc1/TODO | 0
Asrc/cc1/builtin.c | 121+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Rcc1/cc1.h -> src/cc1/cc1.h | 0
Asrc/cc1/code.c | 550+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/cc1/cpp.c | 839+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/cc1/decl.c | 967+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/cc1/deps.mk | 44++++++++++++++++++++++++++++++++++++++++++++
Asrc/cc1/error.c | 85+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/cc1/expr.c | 1185+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/cc1/fold.c | 685+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/cc1/init.c | 378+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Rcc1/ir.md -> src/cc1/ir.md | 0
Asrc/cc1/lex.c | 801+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/cc1/main.c | 102+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/cc1/stmt.c | 386+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/cc1/symbol.c | 353+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/cc1/target/amd64-sysv/arch.c | 220+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/cc1/target/amd64-sysv/arch.mk | 4++++
Asrc/cc1/target/arm64-sysv/arch.c | 220+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/cc1/target/arm64-sysv/arch.mk | 4++++
Asrc/cc1/target/i386-sysv/arch.c | 221+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/cc1/target/i386-sysv/arch.mk | 4++++
Asrc/cc1/target/z80-scc/arch.c | 219+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/cc1/target/z80-scc/arch.mk | 4++++
Asrc/cc1/types.c | 438+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/cc2/.gitignore | 1+
Asrc/cc2/Makefile | 40++++++++++++++++++++++++++++++++++++++++
Rcc2/cc2.h -> src/cc2/cc2.h | 0
Asrc/cc2/code.c | 133+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/cc2/deps.mk | 61+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Rcc2/generror.awk -> src/cc2/generror.awk | 0
Asrc/cc2/main.c | 70++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/cc2/node.c | 142+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/cc2/optm.c | 9+++++++++
Asrc/cc2/parser.c | 722+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/cc2/peep.c | 8++++++++
Asrc/cc2/symbol.c | 92+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Rcc2/target/amd64-sysv/arch.h -> src/cc2/target/amd64-sysv/arch.h | 0
Asrc/cc2/target/amd64-sysv/cgen.c | 15+++++++++++++++
Asrc/cc2/target/amd64-sysv/code.c | 211+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/cc2/target/amd64-sysv/optm.c | 11+++++++++++
Asrc/cc2/target/amd64-sysv/target.mk | 8++++++++
Asrc/cc2/target/amd64-sysv/types.c | 94+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Rcc2/target/arm64-sysv/types.c -> src/cc2/target/arm64-sysv/types.c | 0
Rcc2/target/i386-sysv/arch.h -> src/cc2/target/i386-sysv/arch.h | 0
Asrc/cc2/target/i386-sysv/cgen.c | 16++++++++++++++++
Asrc/cc2/target/i386-sysv/code.c | 209+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/cc2/target/i386-sysv/optm.c | 11+++++++++++
Asrc/cc2/target/i386-sysv/target.mk | 8++++++++
Asrc/cc2/target/i386-sysv/types.c | 95+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Rcc2/target/qbe/arch.h -> src/cc2/target/qbe/arch.h | 0
Asrc/cc2/target/qbe/cgen.c | 729+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/cc2/target/qbe/code.c | 569+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/cc2/target/qbe/optm.c | 58++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/cc2/target/qbe_amd64-sysv/target.mk | 8++++++++
Asrc/cc2/target/qbe_arm64-sysv/target.mk | 5+++++
Rcc2/target/z80-scc/arch.h -> src/cc2/target/z80-scc/arch.h | 0
Asrc/cc2/target/z80-scc/cgen.c | 161+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/cc2/target/z80-scc/code.c | 229+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/cc2/target/z80-scc/optm.c | 11+++++++++++
Asrc/cc2/target/z80-scc/target.mk | 8++++++++
Asrc/cc2/target/z80-scc/types.c | 95+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/driver/Makefile | 8++++++++
Asrc/driver/posix/Makefile | 40++++++++++++++++++++++++++++++++++++++++
Asrc/driver/posix/config.h | 5+++++
Rdriver/posix/config.sh -> src/driver/posix/config.sh | 0
Rdriver/posix/cpp.sh -> src/driver/posix/cpp.sh | 0
Rdriver/posix/deps.mk -> src/driver/posix/deps.mk | 0
Rdriver/posix/scc.c -> src/driver/posix/scc.c | 0
Asrc/ld/Makefile | 21+++++++++++++++++++++
Asrc/ld/coff32.c | 403+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/ld/deps.mk | 15+++++++++++++++
Rld/ld.h -> src/ld/ld.h | 0
Asrc/ld/main.c | 288+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/ld/obj.c | 153+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Rlib/c/.gitignore -> src/libc/.gitignore | 0
Asrc/libc/Makefile | 30++++++++++++++++++++++++++++++
Rlib/c/arch/.gitignore -> src/libc/arch/.gitignore | 0
Rlib/c/arch/Makefile -> src/libc/arch/Makefile | 0
Rlib/c/arch/amd64/Makefile -> src/libc/arch/amd64/Makefile | 0
Rlib/c/arch/amd64/dragonfly/.gitignore -> src/libc/arch/amd64/dragonfly/.gitignore | 0
Rlib/c/arch/amd64/dragonfly/Makefile -> src/libc/arch/amd64/dragonfly/Makefile | 0
Rlib/c/arch/amd64/dragonfly/_getheap.s -> src/libc/arch/amd64/dragonfly/_getheap.s | 0
Rlib/c/arch/amd64/dragonfly/_sigaction.c -> src/libc/arch/amd64/dragonfly/_sigaction.c | 0
Rlib/c/arch/amd64/dragonfly/_tzone.c -> src/libc/arch/amd64/dragonfly/_tzone.c | 0
Rlib/c/arch/amd64/dragonfly/gensys.sh -> src/libc/arch/amd64/dragonfly/gensys.sh | 0
Rlib/c/arch/amd64/dragonfly/getenv.c -> src/libc/arch/amd64/dragonfly/getenv.c | 0
Rlib/c/arch/amd64/dragonfly/raise.c -> src/libc/arch/amd64/dragonfly/raise.c | 0
Rlib/c/arch/amd64/dragonfly/signal.c -> src/libc/arch/amd64/dragonfly/signal.c | 0
Rlib/c/arch/amd64/dragonfly/syscall.lst -> src/libc/arch/amd64/dragonfly/syscall.lst | 0
Rlib/c/arch/amd64/dragonfly/time.c -> src/libc/arch/amd64/dragonfly/time.c | 0
Rlib/c/arch/amd64/linux/.gitignore -> src/libc/arch/amd64/linux/.gitignore | 0
Rlib/c/arch/amd64/linux/Makefile -> src/libc/arch/amd64/linux/Makefile | 0
Rlib/c/arch/amd64/linux/_cerrno.s -> src/libc/arch/amd64/linux/_cerrno.s | 0
Rlib/c/arch/amd64/linux/_getheap.s -> src/libc/arch/amd64/linux/_getheap.s | 0
Rlib/c/arch/amd64/linux/_sigaction.c -> src/libc/arch/amd64/linux/_sigaction.c | 0
Rlib/c/arch/amd64/linux/_tzone.c -> src/libc/arch/amd64/linux/_tzone.c | 0
Rlib/c/arch/amd64/linux/errno.lst -> src/libc/arch/amd64/linux/errno.lst | 0
Rlib/c/arch/amd64/linux/gensys.sh -> src/libc/arch/amd64/linux/gensys.sh | 0
Rlib/c/arch/amd64/linux/getenv.c -> src/libc/arch/amd64/linux/getenv.c | 0
Rlib/c/arch/amd64/linux/raise.c -> src/libc/arch/amd64/linux/raise.c | 0
Rlib/c/arch/amd64/linux/signal.c -> src/libc/arch/amd64/linux/signal.c | 0
Rlib/c/arch/amd64/linux/syscall.lst -> src/libc/arch/amd64/linux/syscall.lst | 0
Rlib/c/arch/amd64/linux/time.c -> src/libc/arch/amd64/linux/time.c | 0
Rlib/c/arch/amd64/longjmp.s -> src/libc/arch/amd64/longjmp.s | 0
Rlib/c/arch/amd64/netbsd/.gitignore -> src/libc/arch/amd64/netbsd/.gitignore | 0
Rlib/c/arch/amd64/netbsd/Makefile -> src/libc/arch/amd64/netbsd/Makefile | 0
Rlib/c/arch/amd64/netbsd/_getheap.s -> src/libc/arch/amd64/netbsd/_getheap.s | 0
Rlib/c/arch/amd64/netbsd/_setcontext.s -> src/libc/arch/amd64/netbsd/_setcontext.s | 0
Rlib/c/arch/amd64/netbsd/_sigaction.c -> src/libc/arch/amd64/netbsd/_sigaction.c | 0
Rlib/c/arch/amd64/netbsd/_sigaction2.s -> src/libc/arch/amd64/netbsd/_sigaction2.s | 0
Rlib/c/arch/amd64/netbsd/_tzone.c -> src/libc/arch/amd64/netbsd/_tzone.c | 0
Rlib/c/arch/amd64/netbsd/errno.lst -> src/libc/arch/amd64/netbsd/errno.lst | 0
Rlib/c/arch/amd64/netbsd/gensys.sh -> src/libc/arch/amd64/netbsd/gensys.sh | 0
Rlib/c/arch/amd64/netbsd/getenv.c -> src/libc/arch/amd64/netbsd/getenv.c | 0
Rlib/c/arch/amd64/netbsd/raise.c -> src/libc/arch/amd64/netbsd/raise.c | 0
Rlib/c/arch/amd64/netbsd/signal.c -> src/libc/arch/amd64/netbsd/signal.c | 0
Rlib/c/arch/amd64/netbsd/syscall.lst -> src/libc/arch/amd64/netbsd/syscall.lst | 0
Rlib/c/arch/amd64/netbsd/time.c -> src/libc/arch/amd64/netbsd/time.c | 0
Rlib/c/arch/amd64/openbsd/.gitignore -> src/libc/arch/amd64/openbsd/.gitignore | 0
Rlib/c/arch/amd64/openbsd/Makefile -> src/libc/arch/amd64/openbsd/Makefile | 0
Rlib/c/arch/amd64/openbsd/_getheap.s -> src/libc/arch/amd64/openbsd/_getheap.s | 0
Rlib/c/arch/amd64/openbsd/_sigaction.c -> src/libc/arch/amd64/openbsd/_sigaction.c | 0
Rlib/c/arch/amd64/openbsd/_tzone.c -> src/libc/arch/amd64/openbsd/_tzone.c | 0
Rlib/c/arch/amd64/openbsd/errno.lst -> src/libc/arch/amd64/openbsd/errno.lst | 0
Rlib/c/arch/amd64/openbsd/gensys.sh -> src/libc/arch/amd64/openbsd/gensys.sh | 0
Rlib/c/arch/amd64/openbsd/getenv.c -> src/libc/arch/amd64/openbsd/getenv.c | 0
Rlib/c/arch/amd64/openbsd/raise.c -> src/libc/arch/amd64/openbsd/raise.c | 0
Rlib/c/arch/amd64/openbsd/signal.c -> src/libc/arch/amd64/openbsd/signal.c | 0
Rlib/c/arch/amd64/openbsd/syscall.lst -> src/libc/arch/amd64/openbsd/syscall.lst | 0
Rlib/c/arch/amd64/openbsd/time.c -> src/libc/arch/amd64/openbsd/time.c | 0
Rlib/c/arch/amd64/setjmp.s -> src/libc/arch/amd64/setjmp.s | 0
Rlib/c/arch/arm32/Makefile -> src/libc/arch/arm32/Makefile | 0
Rlib/c/arch/arm32/linux/.gitignore -> src/libc/arch/arm32/linux/.gitignore | 0
Rlib/c/arch/arm32/linux/Makefile -> src/libc/arch/arm32/linux/Makefile | 0
Rlib/c/arch/arm32/linux/_cerrno.s -> src/libc/arch/arm32/linux/_cerrno.s | 0
Rlib/c/arch/arm32/linux/_getheap.s -> src/libc/arch/arm32/linux/_getheap.s | 0
Rlib/c/arch/arm32/linux/_open.c -> src/libc/arch/arm32/linux/_open.c | 0
Rlib/c/arch/arm32/linux/_tzone.c -> src/libc/arch/arm32/linux/_tzone.c | 0
Rlib/c/arch/arm32/linux/gensys.sh -> src/libc/arch/arm32/linux/gensys.sh | 0
Rlib/c/arch/arm32/linux/getenv.c -> src/libc/arch/arm32/linux/getenv.c | 0
Rlib/c/arch/arm32/linux/raise.c -> src/libc/arch/arm32/linux/raise.c | 0
Rlib/c/arch/arm32/linux/signal.c -> src/libc/arch/arm32/linux/signal.c | 0
Rlib/c/arch/arm32/linux/syscall.lst -> src/libc/arch/arm32/linux/syscall.lst | 0
Rlib/c/arch/amd64/dragonfly/time.c -> src/libc/arch/arm32/linux/time.c | 0
Asrc/libc/arch/arm32/longjmp.s | 11+++++++++++
Asrc/libc/arch/arm32/setjmp.s | 9+++++++++
Rlib/c/arch/arm32/Makefile -> src/libc/arch/arm64/Makefile | 0
Rlib/c/arch/arm32/linux/.gitignore -> src/libc/arch/arm64/linux/.gitignore | 0
Rlib/c/arch/arm32/linux/Makefile -> src/libc/arch/arm64/linux/Makefile | 0
Asrc/libc/arch/arm64/linux/_cerrno.s | 13+++++++++++++
Asrc/libc/arch/arm64/linux/_getheap.s | 6++++++
Rlib/c/arch/arm32/linux/_open.c -> src/libc/arch/arm64/linux/_open.c | 0
Rlib/c/arch/amd64/dragonfly/_sigaction.c -> src/libc/arch/arm64/linux/_sigaction.c | 0
Rlib/c/arch/amd64/dragonfly/_tzone.c -> src/libc/arch/arm64/linux/_tzone.c | 0
Asrc/libc/arch/arm64/linux/gensys.sh | 21+++++++++++++++++++++
Rlib/c/arch/amd64/dragonfly/getenv.c -> src/libc/arch/arm64/linux/getenv.c | 0
Rlib/c/arch/amd64/dragonfly/raise.c -> src/libc/arch/arm64/linux/raise.c | 0
Rlib/c/arch/amd64/dragonfly/signal.c -> src/libc/arch/arm64/linux/signal.c | 0
Asrc/libc/arch/arm64/linux/syscall.lst | 11+++++++++++
Rlib/c/arch/amd64/dragonfly/time.c -> src/libc/arch/arm64/linux/time.c | 0
Asrc/libc/arch/arm64/longjmp.s | 22++++++++++++++++++++++
Asrc/libc/arch/arm64/setjmp.s | 20++++++++++++++++++++
Asrc/libc/arch/generrno.sh | 35+++++++++++++++++++++++++++++++++++
Asrc/libc/arch/generrstr.sh | 23+++++++++++++++++++++++
Asrc/libc/arch/mkerrstr | 24++++++++++++++++++++++++
Asrc/libc/arch/posix/_tzone.c | 27+++++++++++++++++++++++++++
Asrc/libc/arch/posix/getenv.c | 18++++++++++++++++++
Asrc/libc/arch/posix/geterrno.sh | 8++++++++
Asrc/libc/arch/posix/raise.c | 11+++++++++++
Asrc/libc/arch/posix/signal.c | 17+++++++++++++++++
Asrc/libc/arch/posix/time.c | 21+++++++++++++++++++++
Asrc/libc/arch/rules.mk | 6++++++
Asrc/libc/assert/Makefile | 10++++++++++
Asrc/libc/assert/__assert.c | 9+++++++++
Asrc/libc/assert/assert.c | 13+++++++++++++
Asrc/libc/ctype/Makefile | 24++++++++++++++++++++++++
Asrc/libc/ctype/ctype.c | 22++++++++++++++++++++++
Asrc/libc/ctype/isalnum.c | 8++++++++
Asrc/libc/ctype/isalpha.c | 8++++++++
Asrc/libc/ctype/isascii.c | 8++++++++
Asrc/libc/ctype/isblank.c | 7+++++++
Asrc/libc/ctype/iscntrl.c | 8++++++++
Asrc/libc/ctype/isdigit.c | 8++++++++
Asrc/libc/ctype/isgraph.c | 8++++++++
Asrc/libc/ctype/islower.c | 8++++++++
Asrc/libc/ctype/isprint.c | 8++++++++
Asrc/libc/ctype/ispunct.c | 8++++++++
Asrc/libc/ctype/isspace.c | 8++++++++
Asrc/libc/ctype/isupper.c | 8++++++++
Asrc/libc/ctype/isxdigit.c | 8++++++++
Asrc/libc/ctype/tolower.c | 9+++++++++
Asrc/libc/ctype/toupper.c | 8++++++++
Asrc/libc/libc.h | 42++++++++++++++++++++++++++++++++++++++++++
Asrc/libc/locale/Makefile | 10++++++++++
Asrc/libc/locale/localeconv.c | 29+++++++++++++++++++++++++++++
Asrc/libc/locale/setlocale.c | 16++++++++++++++++
Asrc/libc/mklst | 12++++++++++++
Asrc/libc/stdio/Makefile | 47+++++++++++++++++++++++++++++++++++++++++++++++
Asrc/libc/stdio/__getc.c | 39+++++++++++++++++++++++++++++++++++++++
Asrc/libc/stdio/__iob.c | 20++++++++++++++++++++
Asrc/libc/stdio/__putc.c | 78++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/libc/stdio/_allocbuf.c | 21+++++++++++++++++++++
Asrc/libc/stdio/_flsbuf.c | 23+++++++++++++++++++++++
Asrc/libc/stdio/_fpopen.c | 75+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/libc/stdio/clearerr.c | 8++++++++
Asrc/libc/stdio/fclose.c | 32++++++++++++++++++++++++++++++++
Asrc/libc/stdio/feof.c | 8++++++++
Asrc/libc/stdio/ferror.c | 8++++++++
Asrc/libc/stdio/fgetc.c | 8++++++++
Asrc/libc/stdio/fgets.c | 19+++++++++++++++++++
Asrc/libc/stdio/fopen.c | 23+++++++++++++++++++++++
Asrc/libc/stdio/fprintf.c | 15+++++++++++++++
Asrc/libc/stdio/fputc.c | 8++++++++
Asrc/libc/stdio/fputs.c | 12++++++++++++
Asrc/libc/stdio/fread.c | 25+++++++++++++++++++++++++
Asrc/libc/stdio/freopen.c | 14++++++++++++++
Asrc/libc/stdio/fseek.c | 26++++++++++++++++++++++++++
Asrc/libc/stdio/ftell.c | 27+++++++++++++++++++++++++++
Asrc/libc/stdio/fwrite.c | 24++++++++++++++++++++++++
Asrc/libc/stdio/getc.c | 8++++++++
Asrc/libc/stdio/getchar.c | 8++++++++
Asrc/libc/stdio/gets.c | 17+++++++++++++++++
Asrc/libc/stdio/perror.c | 16++++++++++++++++
Asrc/libc/stdio/printf.c | 15+++++++++++++++
Asrc/libc/stdio/putc.c | 8++++++++
Asrc/libc/stdio/putchar.c | 8++++++++
Asrc/libc/stdio/puts.c | 12++++++++++++
Asrc/libc/stdio/rewind.c | 10++++++++++
Asrc/libc/stdio/setbuf.c | 8++++++++
Asrc/libc/stdio/setvbuf.c | 48++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/libc/stdio/snprintf.c | 16++++++++++++++++
Asrc/libc/stdio/sprintf.c | 16++++++++++++++++
Asrc/libc/stdio/tmpnam.c | 31+++++++++++++++++++++++++++++++
Asrc/libc/stdio/vfprintf.c | 362+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/libc/stdio/vprintf.c | 12++++++++++++
Asrc/libc/stdio/vsnprintf.c | 25+++++++++++++++++++++++++
Asrc/libc/stdio/vsprintf.c | 12++++++++++++
Asrc/libc/stdlib/Makefile | 25+++++++++++++++++++++++++
Asrc/libc/stdlib/abort.c | 10++++++++++
Asrc/libc/stdlib/abs.c | 8++++++++
Asrc/libc/stdlib/atexit.c | 17+++++++++++++++++
Asrc/libc/stdlib/atoi.c | 25+++++++++++++++++++++++++
Asrc/libc/stdlib/atol.c | 26++++++++++++++++++++++++++
Asrc/libc/stdlib/atoll.c | 26++++++++++++++++++++++++++
Asrc/libc/stdlib/bsearch.c | 26++++++++++++++++++++++++++
Asrc/libc/stdlib/calloc.c | 18++++++++++++++++++
Asrc/libc/stdlib/errno.c | 1+
Asrc/libc/stdlib/exit.c | 13+++++++++++++
Asrc/libc/stdlib/labs.c | 8++++++++
Asrc/libc/stdlib/llabs.c | 8++++++++
Asrc/libc/stdlib/malloc.c | 158+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/libc/stdlib/malloc.h | 16++++++++++++++++
Asrc/libc/stdlib/qsort.c | 68++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/libc/stdlib/rand.c | 18++++++++++++++++++
Asrc/libc/stdlib/realloc.c | 68++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/libc/stdlib/strtoull.c | 64++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/libc/string/Makefile | 31+++++++++++++++++++++++++++++++
Asrc/libc/string/memchr.c | 12++++++++++++
Asrc/libc/string/memcmp.c | 14++++++++++++++
Asrc/libc/string/memcpy.c | 13+++++++++++++
Asrc/libc/string/memmove.c | 18++++++++++++++++++
Asrc/libc/string/memset.c | 12++++++++++++
Asrc/libc/string/strcat.c | 14++++++++++++++
Asrc/libc/string/strchr.c | 10++++++++++
Asrc/libc/string/strcmp.c | 10++++++++++
Asrc/libc/string/strcoll.c | 10++++++++++
Asrc/libc/string/strcpy.c | 12++++++++++++
Asrc/libc/string/strcspn.c | 21+++++++++++++++++++++
Asrc/libc/string/strerror.c | 11+++++++++++
Asrc/libc/string/strlen.c | 12++++++++++++
Asrc/libc/string/strncat.c | 15+++++++++++++++
Asrc/libc/string/strncmp.c | 14++++++++++++++
Asrc/libc/string/strncpy.c | 14++++++++++++++
Asrc/libc/string/strnlen.c | 13+++++++++++++
Asrc/libc/string/strpbrk.c | 20++++++++++++++++++++
Asrc/libc/string/strrchr.c | 14++++++++++++++
Asrc/libc/string/strspn.c | 21+++++++++++++++++++++
Asrc/libc/string/strstr.c | 18++++++++++++++++++
Asrc/libc/string/strtok.c | 25+++++++++++++++++++++++++
Asrc/libc/string/strxfrm.c | 12++++++++++++
Asrc/libc/syscall.h | 8++++++++
Asrc/libc/time/Makefile | 16++++++++++++++++
Asrc/libc/time/_daysyear.c | 30++++++++++++++++++++++++++++++
Asrc/libc/time/asctime.c | 12++++++++++++
Asrc/libc/time/ctime.c | 8++++++++
Asrc/libc/time/difftime.c | 8++++++++
Asrc/libc/time/gmtime.c | 36++++++++++++++++++++++++++++++++++++
Asrc/libc/time/localtime.c | 22++++++++++++++++++++++
Asrc/libc/time/mktime.c | 113+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/libc/time/strftime.c | 247+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/libcoff32/Makefile | 25+++++++++++++++++++++++++
Asrc/libcoff32/coff32_pack_aout.c | 9+++++++++
Asrc/libcoff32/coff32_pack_ent.c | 20++++++++++++++++++++
Asrc/libcoff32/coff32_pack_hdr.c | 21+++++++++++++++++++++
Asrc/libcoff32/coff32_pack_scn.c | 24++++++++++++++++++++++++
Asrc/libcoff32/coff32_unpack_aout.c | 9+++++++++
Asrc/libcoff32/coff32_unpack_ent.c | 20++++++++++++++++++++
Asrc/libcoff32/coff32_unpack_hdr.c | 22++++++++++++++++++++++
Asrc/libcoff32/coff32_unpack_scn.c | 24++++++++++++++++++++++++
Asrc/libcoff32/deps.mk | 17+++++++++++++++++
Asrc/libcrt/Makefile | 11+++++++++++
Asrc/libcrt/crt-amd64-posix.s | 19+++++++++++++++++++
Asrc/libcrt/crt-arm32-posix.s | 16++++++++++++++++
Asrc/libcrt/crt-arm64-posix.s | 16++++++++++++++++
Asrc/libcrt/crt-dragonfly.s | 1+
Asrc/libcrt/crt-linux.s | 1+
Asrc/libcrt/crt-netbsd.s | 9+++++++++
Asrc/libcrt/crt-openbsd.s | 9+++++++++
Asrc/libscc/Makefile | 31+++++++++++++++++++++++++++++++
Asrc/libscc/alloc.c | 112+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/libscc/bpack.c | 64++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/libscc/bunpack.c | 71+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/libscc/casecmp.c | 11+++++++++++
Asrc/libscc/debug.c | 20++++++++++++++++++++
Asrc/libscc/deps.mk | 18++++++++++++++++++
Asrc/libscc/die.c | 20++++++++++++++++++++
Asrc/libscc/lpack.c | 64++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/libscc/lunpack.c | 71+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/libscc/newitem.c | 12++++++++++++
Asrc/libscc/rmyro.c | 94+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/libscc/wmyro.c | 86+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/libscc/xcalloc.c | 13+++++++++++++
Asrc/libscc/xmalloc.c | 13+++++++++++++
Asrc/libscc/xrealloc.c | 13+++++++++++++
Asrc/libscc/xstrdup.c | 12++++++++++++
Asrc/nm/Makefile | 21+++++++++++++++++++++
Asrc/nm/coff32.c | 312+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/nm/deps.mk | 11+++++++++++
Asrc/nm/formats.c | 13+++++++++++++
Asrc/nm/main.c | 272+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/nm/nm.h | 14++++++++++++++
Asrc/objdump/Makefile | 16++++++++++++++++
Asrc/objdump/deps.mk | 4++++
Asrc/objdump/main.c | 333+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mtests/Makefile | 2+-
828 files changed, 23471 insertions(+), 23623 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -1,23 +1,6 @@ *.o *.a -root/libexec/scc/cc1-* -root/libexec/scc/cc2-* -root/libexec/scc/as-* -root/bin/ld -root/bin/scc -root/bin/scpp -root/bin/ar -root/bin/nm -root/bin/objdump -test.log -cc2/error.h -instbl.c -config.mk -inc/ldflags.h -inc/sysincludes.h -inc/syslibs.h -inc/syscrts.h -driver/posix/config.h -as/target/*/*tbl.c -*.out -config +bin/ +lib/ +libexec/ +dirs diff --git a/Makefile b/Makefile @@ -1,34 +1,32 @@ -# scc - Suckless C Compiler .POSIX: PROJECTDIR = . +include $(PROJECTDIR)/scripts/rules.mk -include rules.mk +DIRS = src include/scc/scc tests -DIRS = inc cc1 cc2 driver lib as ar nm objdump ld +all: src -all: $(DIRS) +src: dirs include/scc/scc -$(DIRS): config FORCE - +@cd $@ && $(MAKE) all +dirs: $(SCRIPTDIR)/libc-proto + xargs mkdir -p < $(SCRIPTDIR)/libc-proto + touch dirs -clean dep: - $(FORALL) +$(DIRS): FORCE + +@cd $@ && $(MAKE) -distclean: unconfig +dep: $(FORALL) - rm -f config -tests: all - +@cd tests && $(MAKE) -e all +clean: + $(FORALL) + rm -rf lib bin libexec dirs -unconfig: - (echo '/^### Systems/,$$ v/^#/ s/^/#/' ; echo w) | ed -s config.mk - rm -f config +distclean: clean + +@cd include/scc/scc && $(MAKE) distclean -config: - ./config.sh - touch $@ +tests: all install: all mkdir -p $(DESTDIR)$(PREFIX)/ diff --git a/ar/Makefile b/ar/Makefile @@ -1,22 +0,0 @@ -.POSIX: - -PROJECTDIR = .. -include $(PROJECTDIR)/rules.mk -include $(LIBSCC)/libdep.mk - -OBJ = main.o $(DRIVER)/driver.o -MORECFLAGS = -I$(DRIVER) -STDCFLAGS = - -all: $(BINDIR)/ar - -$(BINDIR)/ar: $(OBJ) $(LIBDIR)/libscc.a - $(CC) $(SCC_LDFLAGS) $(OBJ) -lscc -o $@ - -dep: - $(PROJECTDIR)/mkdep.sh - -clean: - rm -f *.o $(DRIVER)/*.o $(BINDIR)/ar - -include deps.mk diff --git a/ar/deps.mk b/ar/deps.mk @@ -1,7 +0,0 @@ -main.o: $(DRIVER)/driver.h - -#deps -main.o: ../inc/ar.h -main.o: ../inc/arg.h -main.o: ../inc/scc.h -posix/driver.o: posix/driver.h diff --git a/ar/main.c b/ar/main.c @@ -1,643 +0,0 @@ -static char sccsid[] = "@(#) ./ar/main.c"; - -#include <errno.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> - -#include <driver.h> - -#include "../inc/ar.h" -#include "../inc/arg.h" -#include "../inc/scc.h" - -enum { - BEFORE, - INDOT, - AFTER, -}; - -struct tmp { - char *name; - FILE *fp; -} tmps[3]; - -char *argv0; - -static int bflag, vflag, cflag, lflag, uflag, aflag; -static char *arfile, *posname; - -struct member { - FILE *src; - struct ar_hdr hdr; - int cur; - char *fname; - long size; - long mode; - long long date; -}; - -static void -cleanup(void) -{ - int i; - - for (i = 0; i < 3; i++) { - if (tmps[i].name) - remove(tmps[i].name); - } -} - -/* - * I do know that you cannot call remove from a signal handler - * but we only can use stdio function to deal with files - * because we are C99 compliant, and it is very likely that - * remove is going to work in this case - */ -static void -sigfun(int signum) -{ - cleanup(); - _Exit(1); -} - -static FILE * -openar(void) -{ - FILE *fp; - char magic[SARMAG+1]; - - if ((fp = fopen(arfile,"r+b")) == NULL) { - if (!cflag) - fprintf(stderr, "ar: creating %s\n", arfile); - if ((fp = fopen(arfile, "w+b")) == NULL) { - perror("ar:opening archive"); - exit(1); - } - fputs(ARMAG, fp); - if (fflush(fp) == EOF) { - perror("ar:writing magic number"); - exit(1); - } - } else { - if (fgets(magic, sizeof(magic), fp) == NULL) { - perror("ar:error reading magic number"); - exit(1); - } - if (strcmp(magic, ARMAG)) { - fprintf(stderr, - "ar:%s:invalid magic number '%s'\n", - arfile, - magic); - exit(1); - } - } - return fp; -} - -static void -archive(char *fname, FILE *to, char letter) -{ - int c; - size_t n; - FILE *from; - char mtime[13]; - struct stat st; - - if (vflag) - printf("%c - %s\n", letter, fname); - if (strlen(fname) > 16) - fprintf(stderr, "ar:%s: too long name\n", fname); - if ((from = fopen(fname, "rb")) == NULL) { - fprintf(stderr, - "ar:opening member '%s':%s\n", - fname, - strerror(errno)); - exit(1); - } - if (stat(fname, &st) < 0) { - fprintf(stderr, "ar:error getting '%s' attributes\n", fname); - exit(1); - } - strftime(mtime, sizeof(mtime), "%s", gmtime(&st.st_mtime)); - fprintf(to, - "%-16.16s%-12s%-6u%-6u%-8o%-10llu`\n", - fname, - mtime, - st.st_uid, - st.st_gid, - st.st_mode, - (unsigned long long) st.st_size); - for (n = 0; (c = getc(from)) != EOF; n++) - putc(c, to); - if (n & 1) - putc('\n', to); - if (ferror(from)) { - fprintf(stderr, - "ar:reading input '%s':%s\n", - fname, strerror(errno)); - exit(1); - } - fclose(from); -} - -static void -append(FILE *fp, char *argv[]) -{ - char *fname; - - if (fseek(fp, 0, SEEK_END) == EOF) { - perror("ar:seeking archive"); - exit(1); - } - - for ( ; fname = *argv; ++argv) { - *argv = NULL; - archive(fname, fp, 'a'); - } - - if (fclose(fp) == EOF) { - perror("ar:error writing archive"); - exit(1); - } -} - -static void -copy(struct member *m, struct tmp *tmp) -{ - int c; - size_t siz = m->size; - struct ar_hdr *hdr = &m->hdr; - - fwrite(hdr, sizeof(*hdr), 1, tmp->fp); - if ((siz & 1) == 1) - siz++; - while (siz--) { - if ((c = getc(m->src)) == EOF) - break; - fputc(c, tmp->fp); - } -} - -static void -letters(unsigned long val, char *s) -{ - *s++ = (val & 04) ? 'r' : '-'; - *s++ = (val & 02) ? 'w' : '-'; - *s++ = (val & 01) ? 'x' : '-'; -} - -static char * -perms(struct member *m) -{ - static char buf[10]; - - letters(m->mode >> 6, buf); - letters(m->mode >> 3, buf+3); - letters(m->mode, buf +6); - buf[9] = '\0'; - - return buf; -} - -static int -inlist(char *fname, int argc, char *argv[]) -{ - for (; argc-- > 0; ++argv) { - if (*argv && !strcmp(*argv, fname)) { - *argv = NULL; - return 1; - } - } - return 0; -} - -static void -move(struct member *m, int argc, char *argv[]) -{ - int where; - - if (inlist(m->fname, argc, argv)) { - if (vflag) - printf("m - %s\n", m->fname); - where = INDOT; - } else if (posname && !strcmp(posname, m->fname)) { - where = (bflag) ? AFTER : BEFORE; - m->cur = AFTER; - } else { - where = m->cur; - } - copy(m, &tmps[where]); -} - -static void -insert(int argc, char *argv[]) -{ - for (; argc-- > 0; ++argv) { - if (*argv) { - archive(*argv, tmps[INDOT].fp, 'a'); - *argv = NULL; - } - } -} - -static void -update(struct member *m, int argc, char *argv[]) -{ - int where; - FILE *fp = tmps[BEFORE].fp; - - if (inlist(m->fname, argc, argv)) { - archive(m->fname, tmps[m->cur].fp, 'r'); - return; - } else if (posname && !strcmp(posname, m->fname)) { - where = (bflag) ? AFTER : BEFORE; - m->cur = AFTER; - } else { - where = m->cur; - } - copy(m, &tmps[where]); -} - -static void -extract(struct member *m, int argc, char *argv[]) -{ - int c; - long siz; - FILE *fp; - - if (argc > 0 && !inlist(m->fname, argc, argv)) - return; - if (vflag) - printf("x - %s\n", m->fname); - siz = m->size; - - if ((fp = fopen(m->fname, "wb")) == NULL) - goto error_file; - while (siz-- > 0 && (c = getc(m->src)) != EOF) - putc(c, fp); - fflush(fp); - if (fclose(fp) == EOF) - goto error_file; - - /* TODO: set attributes */ - return; - - -error_file: - perror("ar:error extracting file"); - exit(1); -} - -static void -print(struct member *m, int argc, char *argv[]) -{ - long siz; - int c; - - if (argc > 0 && !inlist(m->fname, argc, argv)) - return; - if (vflag) - printf("\n<%s>\n\n", m->fname); - siz = m->size; - while (siz-- > 0 && (c = getc(m->src)) != EOF) - putchar(c); -} - -static void -list(struct member *m, int argc, char *argv[]) -{ - time_t t; - struct ar_hdr *hdr = &m->hdr; - char mtime[30]; - - if (argc > 0 && !inlist(m->fname, argc, argv)) - return; - if (!vflag) { - printf("%s\n", m->fname); - } else { - t = totime(m->date); - strftime(mtime, sizeof(mtime), "%c", localtime(&t)); - printf("%s %ld/%ld\t%s %s\n", - perms(m), - atol(hdr->ar_uid), - atol(hdr->ar_gid), - mtime, - m->fname); - } -} - -static void -del(struct member *m, int argc, char *argv[]) -{ - if (inlist(m->fname, argc, argv)) { - if (vflag) - printf("d - %s\n", m->fname); - return; - } - copy(m, &tmps[BEFORE]); -} - -static char * -getfname(struct ar_hdr *hdr) -{ - static char fname[SARNAM+1]; - size_t i; - - memcpy(fname, hdr->ar_name, SARNAM); - fname[SARNAM] = '\0'; - - for (i = SARNAM-1; i >= 0; --i) { - if (fname[i] != ' ' && fname[i] != '/') - break; - fname[i] = '\0'; - } - return fname; -} - -static long long -getnum(char *s, int size, int base) -{ - int c; - long long val; - char *p; - static char digits[] = "0123456789"; - - for (val = 0; size > 0; val += c) { - --size; - if ((c = *s++) == ' ') - break; - if ((p = strchr(digits, c)) == NULL) - return -1; - if ((c = p - digits) >= base) - return -1; - val *= base; - } - - while (size > 0 && *s++ == ' ') - --size; - return (size == 0) ? val : -1; -} - -static int -valid(struct member *m) -{ - struct ar_hdr *hdr = &m->hdr; - - m->fname = getfname(&m->hdr); - m->size = getnum(hdr->ar_size, sizeof(hdr->ar_size), 10); - m->mode = getnum(hdr->ar_mode, sizeof(hdr->ar_mode), 8); - m->date = getnum(hdr->ar_date, sizeof(hdr->ar_date), 10); - - if (strncmp(hdr->ar_fmag, ARFMAG, sizeof(hdr->ar_fmag)) || - m->size < 0 || m->mode < 0 || m->date < 0) { - return 0; - } - return 1; -} - -static void -run(FILE *fp, int argc, char *argv[], - void (*fun)(struct member *, int argc, char *files[])) -{ - struct member m; - - m.src = fp; - m.cur = BEFORE; - - while (fread(&m.hdr, sizeof(m.hdr), 1, fp) == 1) { - fpos_t pos; - - if (!valid(&m)) { - fprintf(stderr, - "ar:corrupted member '%s'\n", - m.fname); - exit(1); - } - fgetpos(fp, &pos); - (*fun)(&m, argc, argv); - fsetpos(fp, &pos); - fseek(fp, m.size+1 & ~1, SEEK_CUR); - } - if (ferror(fp) || fclose(fp) == EOF) { - perror("ar:reading members"); - exit(1); - } -} - -static void -merge(void) -{ - FILE *fp, *fi; - int c, i; - - - if ((fp = fopen(arfile, "wb")) == NULL) { - perror("ar:reopening archive"); - exit(1); - } - - fputs(ARMAG, fp); - - for (i = 0; i < 3; i++) { - if ((fi = tmps[i].fp) == NULL) - continue; - fseek(fi, 0, SEEK_SET); - while ((c = getc(fi)) != EOF) - putc(c, fp); - if (ferror(fi)) { - perror("ar:error in temporary"); - exit(1); - } - } - - if (fclose(fp) == EOF) { - perror("ar:writing archive file"); - exit(1); - } -} - -static void -closetmp(int which) -{ - struct tmp *tmp = &tmps[which]; - - if (!tmp->fp) - return; - if (fclose(tmp->fp) == EOF) { - perror("ar:closing temporaries"); - exit(1); - } -} - -static void -opentmp(char *fname, int which) -{ - struct tmp *tmp = &tmps[which]; - - if (lflag) { - tmp->name = fname; - tmp->fp = fopen(fname, "w+b"); - } else { - tmp->fp = tmpfile(); - } - - if (tmp->fp == NULL) { - perror("ar:creating temporary"); - exit(1); - } -} - -static void -doit(int key, char *argv[], int argc) -{ - FILE *fp; - - fp = openar(); - if (argc == 0 && - (key == 'r' || key == 'd' || key == 'm' || key == 'q')) { - if (fclose(fp) == EOF) { - perror("ar:early close of archive file"); - exit(-1); - } - return; - } - - if (key == 'r' || key == 'm' || key == 'd') - opentmp("ar.tmp1", BEFORE); - if (key == 'r' || key == 'm') { - opentmp("ar.tmp2", INDOT); - opentmp("ar.tmp3", AFTER); - } - - switch (key) { - case 'r': - run(fp, argc, argv, update); - insert(argc, argv); - merge(); - break; - case 'm': - run(fp, argc, argv, move); - merge(); - break; - case 'd': - run(fp, argc, argv, del); - merge(); - break; - case 't': - run(fp, argc, argv, list); - break; - case 'p': - run(fp, argc, argv, print); - break; - case 'x': - run(fp, argc, argv, extract); - break; - case 'q': - append(fp, argv); - break; - } - - closetmp(BEFORE); - closetmp(INDOT); - closetmp(AFTER); - - for ( ; argc-- > 0; ++argv) { - if (*argv) { - fprintf(stderr, "ar: No member named '%s'\n", *argv); - exit(1); - } - } -} - -static void -usage(void) -{ - fputs("ar [-drqtpmx][posname] [-vuaibcl] [posname] arfile name ...\n", - stderr); - exit(1); -} - -int -main(int argc, char *argv[]) -{ - int key, nkey = 0, pos = 0; - - atexit(cleanup); - ARGBEGIN { - case 'd': - nkey++; - key = 'd'; - break; - case 'r': - nkey++; - key = 'r'; - break; - case 'q': - nkey++; - key = 'q'; - break; - case 't': - nkey++; - key = 't'; - break; - case 'p': - nkey++; - key = 'p'; - break; - case 'm': - nkey++; - key = 'm'; - break; - case 'x': - nkey++; - key = 'x'; - break; - case 'a': - aflag = 1; - pos++; - posname = EARGF(usage()); - break; - case 'i': - case 'b': - bflag = 1; - pos++; - posname = EARGF(usage()); - break; - case 'v': - vflag = 1; - break; - case 'c': - cflag = 1; - break; - case 'l': - lflag = 1; - break; - case 'u': - /* TODO */ - abort(); - uflag = 1; - break; - default: - usage(); - } ARGEND - - if (nkey == 0 || nkey > 1 || pos > 1 || argc == 0) - usage(); - - signal(SIGINT, sigfun); - signal(SIGQUIT, sigfun); - signal(SIGTERM, sigfun); - - arfile = *argv; - doit(key, ++argv, --argc); - - if (fflush(stdout) == EOF) { - perror("ar:error writing to stdout"); - exit(1); - } - - return 0; -} diff --git a/as/Makefile b/as/Makefile @@ -1,29 +0,0 @@ -.POSIX: - -PROJECTDIR = .. -include $(PROJECTDIR)/rules.mk -include $(LIBSCC)/libdep.mk - -OBJ = main.o symbol.o ins.o parser.o expr.o myro.o -MORECFLAGS = -I$(INCLUDE)/$(STD) -TARGETS = $(LIBEXEC)/as-amd64 $(LIBEXEC)/as-i386 \ - $(LIBEXEC)/as-i286 $(LIBEXEC)/as-z80 - -all: $(TARGETS) - -$(TARGETS): $(LIBDIR)/libscc.a - -dep: - $(PROJECTDIR)/mkdep.sh - -clean: - rm -f *.o target/*/*.o - rm -f target/*/*tbl.c - rm -f as-* - rm -f $(TARGETS) - -include target/amd64.mk -include target/i386.mk -include target/i286.mk -include target/z80.mk -include deps.mk diff --git a/as/deps.mk b/as/deps.mk @@ -1,46 +0,0 @@ -parser.o: $(PROJECTDIR)/inc/$(STD)/cstd.h - -#deps -expr.o: ../inc/scc.h -expr.o: as.h -ins.o: ../inc/scc.h -ins.o: as.h -main.o: ../inc/arg.h -main.o: ../inc/scc.h -main.o: as.h -myro.o: ../inc/myro.h -myro.o: ../inc/scc.h -myro.o: as.h -parser.o: ../inc/scc.h -parser.o: as.h -symbol.o: ../inc/scc.h -symbol.o: as.h -target/x80/ins.o: target/x80/../../../inc/scc.h -target/x80/ins.o: target/x80/../../as.h -target/x80/ins.o: target/x80/proc.h -target/x80/z80.o: target/x80/../../../inc/scc.h -target/x80/z80.o: target/x80/../../as.h -target/x80/z80.o: target/x80/../x80/proc.h -target/x80/z80tbl.o: target/x80/../../../inc/scc.h -target/x80/z80tbl.o: target/x80/../../as.h -target/x80/z80tbl.o: target/x80/../x80/proc.h -target/x86/amd64.o: target/x86/../../../inc/scc.h -target/x86/amd64.o: target/x86/../../as.h -target/x86/amd64tbl.o: target/x86/../../../inc/scc.h -target/x86/amd64tbl.o: target/x86/../../as.h -target/x86/amd64tbl.o: target/x86/../x86/proc.h -target/x86/i286.o: target/x86/../../../inc/scc.h -target/x86/i286.o: target/x86/../../as.h -target/x86/i286.o: target/x86/../x86/proc.h -target/x86/i286tbl.o: target/x86/../../../inc/scc.h -target/x86/i286tbl.o: target/x86/../../as.h -target/x86/i286tbl.o: target/x86/../x86/proc.h -target/x86/i386.o: target/x86/../../../inc/scc.h -target/x86/i386.o: target/x86/../../as.h -target/x86/i386.o: target/x86/../x86/proc.h -target/x86/i386tbl.o: target/x86/../../../inc/scc.h -target/x86/i386tbl.o: target/x86/../../as.h -target/x86/i386tbl.o: target/x86/../x86/proc.h -target/x86/ins.o: target/x86/../../../inc/scc.h -target/x86/ins.o: target/x86/../../as.h -target/x86/ins.o: target/x86/proc.h diff --git a/as/expr.c b/as/expr.c @@ -1,303 +0,0 @@ -static char sccsid[] = "@(#) ./as/expr.c"; - -#include <ctype.h> -#include <stdlib.h> -#include <string.h> - -#include "../inc/scc.h" -#include "as.h" - -#define NNODES 10 - -static Alloc *arena; - -Node * -node(int op, Node *l, Node *r) -{ - struct arena *ap; - Node *np; - - if (!arena) - arena = alloc(sizeof(Node), NNODES); - np = new(arena); - np->op = op; - np->left = l; - np->right = r; - np->sym = NULL; - - return np; -} - -void -deltree(Node *np) -{ - if (!np) - return; - deltree(np->left); - deltree(np->right); - delete(arena, np); -} - -static Node * -fold(int op, Node *l, Node *r) -{ - Node *np; - TUINT val, lv, rv; - - lv = l->sym->value; - rv = r->sym->value; - - /* TODO: check overflow */ - - switch (op) { - case '*': - val = lv - rv; - break; - case '/': - if (rv == 0) - goto division_by_zero; - val = lv / rv; - break; - case '%': - if (rv == 0) - goto division_by_zero; - val = lv % rv; - break; - case SHL: - val = lv << rv; - break; - case SHR: - val = lv >> rv; - break; - case '+': - val = lv + rv; - break; - case '-': - val = lv - rv; - break; - case '<': - val = lv < rv; - break; - case '>': - val = lv > rv; - break; - case '=': - val = lv == rv; - break; - case GE: - val = lv >= rv; - break; - case LE: - val = lv <= rv; - break; - case '|': - val = lv | rv; - break; - case '^': - val = lv ^ rv; - break; - default: - abort(); - } - deltree(l); - deltree(r); - - np = node(NUMBER, NULL, NULL); - np->sym = tmpsym(val); - np->addr = ANUMBER; - return np; - -division_by_zero: - error("division by 0"); -} - -static Node * -binary(int op, Node *l, Node *r) -{ - int addr; - Node *np; - - if (l->op == NUMBER && r->op == NUMBER) - return fold(op, l, r); - else - abort(); - np = node(op, l, r); - np->addr = addr; - - return np; -} - -static Node * -unaryop(int op, Node *np) -{ - TUINT val; - - if (np->addr != ANUMBER) - error("invalid argument for unary operator"); - if (np->op != NUMBER) { - np = node(op, np, NULL); - np->addr = ANUMBER; - return np; - } - - val = np->sym->value; - switch (op) { - case '!': - val = !val; - case '+': - break; - case '-': - val = -val; - break; - default: - abort(); - } - np->sym->value = val; - - return np; -} - -/*************************************************************************/ -/* grammar functions */ -/*************************************************************************/ - -static Node * -primary(void) -{ - Node *np; - - switch (yytoken) { - case IDEN: - case NUMBER: - np = node(yytoken, NULL, NULL); - np->sym = yylval.sym; - np->addr = ANUMBER; - next(); - break; - case '(': - np = expr(); - expect(')'); - break; - default: - unexpected(); - } - - return np; -} - -static Node * -unary(void) -{ - int op, tok; - Node *np; - - switch (tok = yytoken) { - case '!': - case '-': - case '+': - next(); - return unaryop(tok, primary()); - default: - return primary(); - } -} - -static Node * -mul(void) -{ - int op; - Node *np; - - np = unary(); - for (;;) { - switch (op = yytoken) { - case '*': - case '/': - case '%': - case SHL: - case SHR: - next(); - binary(op, np, primary()); - break; - default: - return np; - } - } -} - -static Node * -add(void) -{ - int op; - Node *np; - - np = mul(); - for (;;) { - switch (op = yytoken) { - case '+': - case '-': - next(); - np = binary(op, np, mul()); - break; - default: - return np; - } - } -} - -static Node * -relational(void) -{ - int op; - Node *np; - - np = add(); - for (;;) { - switch (op = yytoken) { - case '<': - case '>': - case '=': - case GE: - case LE: - next(); - np = binary(op, np, add()); - break; - default: - return np; - } - } -} - -static Node * -and(void) -{ - int op; - Node *np; - - np = relational(); - while (accept('&')) - np = binary('&', np, relational()); - return np; -} - -Node * -expr(void) -{ - int op; - Node *np; - - regctx(0); - np = and(); - for (;;) { - switch (op = yytoken) { - case '|': - case '^': - next(); - np = binary(op, np, and()); - break; - default: - regctx(1); - return np; - } - } -} diff --git a/as/gentbl.awk b/as/gentbl.awk @@ -1,112 +0,0 @@ - -BEGIN { - printf "#include \"../../../inc/scc.h\"\n"\ - "#include \"../../as.h\"\n"\ - "#include \"../" family "/proc.h\"\n" - - rules = "target/" family "/rules.dat" - while (getline < rules > 0) { - regex[++nregs] = $1 - value[nregs] = $2 - } - close(rules) -} - {sub(/#.*/,"")} - -$7 !~ cpu {next} - -/^$/ {next} - - { - if (opstart[$1] == 0) { - opstart[$1] = nvar - opnames[nop++] = $1 - } - opcount[$1]++ - opargs[nvar] = $3 - opsize[nvar] = $4 - opbytes[nvar] = ($5 == "none") ? "" : $5 - opformat[nvar++] = $6 - formats[$6] = 1 -} - -END { - for (i in formats) - printf "Format %s;\n", i - - printf "int nr_ins = %d;\n\n", nop - print "struct ins instab[] = {" - for (i = 0; i < nop; i++) { - n = opnames[i] - start = opstart[n] - end = start + opcount[n] - printf "\t{.str = \"%s\", .begin = %d, .end = %d},\n", - n, start, end | "sort" - } - close("sort") - printf "};\n\n" - - print "struct op optab[] = {" - for (i = 0; i < nvar; i++) { - printf "\t/* %d */\n", i - printf "\t{\n" \ - "\t\t.size = %d,\n"\ - "\t\t.format = %s,\n", - opsize[i], opformat[i] - - if (opbytes[i] != "") - printf "\t\t.bytes = (unsigned char [%d]) {%s},\n", - opsize[i], - opbytes[i] - - a = str2args(opargs[i]) - if (a != "") - printf "\t\t.args = (unsigned char []) {%s}\n", a - - print "\t}," - } - print "};" -} - -function str2args(s, args, i, j, out, n, found) -{ - n = split(s, args, /,/) - if (n == 0 || args[1] == "none") - return "" - for (i = 1; i <= n; i++) { - a = args[i] - found = 0 - - if (a ~ /\?$/) - out = out "AOPT ," - else if (a ~ /\+$/) - out = out "AREP ," - - for (j = 1; j <= nregs; j++) { - if (match(a, "^" regex[j])) { - out = out value[j] - found = 1 - break - } - } - - if (!found) { - print FILENAME ":" NR ":" \ - $0 ":wrong arg", a > "/dev/stderr" - exit 1 - } - - a = substr(a, RLENGTH+1) - sub(/\?$/, "", a) - sub(/\+$/, "", a) - if (a != "") { - print FILENAME ":" NR ":" \ - $0 ": trailing chars: ", a > "/dev/stderr" - exit 1 - } - out = out "," - } - out = out "0" - - return out -} diff --git a/as/gentbl.sh b/as/gentbl.sh @@ -1,33 +0,0 @@ -#!/bin/sh - - -set -e - -while test $# -gt 0 -do - case $1 in - -c) - cpu=$2 - shift - ;; - -f) - family=$2 - shift - ;; - *) - echo gen.sh:incorrect parameter:$1 >&2 - exit 1 - ;; - esac - shift -done - -echo cpu=${cpu:=z80} family=${family:=x80} - -rm -f $$.c target/$family/${cpu}tbl.c -trap "rm -f $$.c" 0 2 3 - -awk '!/^$/ {print $1,NR,$2,$3,$4,$5,$6}' target/$family/$family.dat | -LC_COLLATE=C sort -k1 -k2n | -awk -v cpu=`echo $cpu | tr a-z A-Z` -v family=$family -f gentbl.awk > $$.c && -mv $$.c target/$family/${cpu}tbl.c diff --git a/as/ins.c b/as/ins.c @@ -1,249 +0,0 @@ -static char sccsid[] = "@(#) ./as/ins.c"; - -#include <string.h> - -#include "../inc/scc.h" -#include "as.h" - -extern Section *sabs, *sbss, *sdata, *stext; - -enum { - EQU, - COMMON, - SIZE, - XSTRING, - ASCII, - TYPE, -}; - -char * -tobytes(TUINT v, int nbytes, int inc) -{ - static char buf[sizeof(TUINT)]; - int idx; - - idx = (inc < 0) ? nbytes-1 : 0; - while (nbytes--) { - buf[idx] = v; - idx += inc; - v >>= 8; - } - - if (v) - error("overflow in immediate value"); - return buf; -} - -void -noargs(Op *op, Node **args) -{ - emit(op->bytes, op->size); -} - -static void -xstring(int which, Node **args) -{ - Node *np; - char *s; - size_t len; - - while (np = *args++) { - s = np->sym->name.buf; - len = strlen(s); - len += which == XSTRING; - emit(s, len); - } -} - -void -string(Op *op, Node **args) -{ - xstring(STRING, args); -} - -void -ascii(Op *op, Node **args) -{ - xstring(STRING, args); -} - -void -def(Node **args, int siz) -{ - Node *np; - - while (np = *args++) { - Symbol *sym = np->sym; - - if ((sym->flags & FABS) == 0) - reloc(sym, 0, siz, siz * 8, 0); - emit(tobytes(sym->value, siz, endian), siz); - } -} - -void -defb(Op *op, Node **args) -{ - def(args, 1); -} - -void -defw(Op *op, Node **args) -{ - def(args, 2); -} - -void -defd(Op *op, Node **args) -{ - def(args, 4); -} - -void -defq(Op *op, Node **args) -{ - def(args, 8); -} - -static void -symexp(int which, Op *op, Node **args) -{ - Symbol *sym, *exp; - static char *cmds[] = { - [EQU] = "equ", - [COMMON] = "common", - [SIZE] = "size", - }; - char *cmd = cmds[which]; - - if (args[1]) { - sym = args[0]->sym; - exp = args[1]->sym; - } else if (linesym) { - sym = linesym; - exp = args[0]->sym; - } else { - error("%s pseudo instruction lacks a label", cmd); - } - - if ((exp->flags & FABS) == 0) - error("%s expression is not an absolute expression", cmd); - - switch (which) { - case EQU: - if (pass == 1 && (sym->flags & FDEF)) - error("redefinition of symbol '%s'", sym->name.buf); - sym->value = exp->value; - sym->flags |= FDEF; - break; - case COMMON: - sym->flags |= FCOMMON; - case SIZE: - sym->size = exp->value; - break; - case TYPE: - sym->type.buf = xstrdup(exp->name.buf); - break; - } -} - -void -equ(Op *op, Node **args) -{ - symexp(EQU, op, args); -} - -void -common(Op *op, Node **args) -{ - symexp(COMMON, op, args); -} - -void -size(Op *op, Node **args) -{ - symexp(SIZE, op, args); -} - -void -type(Op *op, Node **args) -{ - symexp(TYPE, op, args); -} - -void -section(Op *op, Node **args) -{ - Symbol *sym = args[0]->sym; - char *attr = NULL; - - if (args[1]) - attr = args[1]->sym->name.buf; - - setsec(sym->name.buf, attr); -} - -void -text(Op *op, Node **args) -{ - cursec = stext; -} - -void -data(Op *op, Node **args) -{ - cursec = sdata; -} - -void -bss(Op *op, Node **args) -{ - cursec = sbss; -} - -void -extrn(Op *op, Node **args) -{ - Symbol *sym = args[0]->sym; - - sym->flags |= FEXTERN; -} - -void -global(Op *op, Node **args) -{ - Symbol *sym = args[0]->sym; - - sym->flags |= FGLOBAL; -} - -void -align(Op *op, Node **args) -{ - Symbol *sym = args[0]->sym; - TUINT curpc, pc, al; - - if ((sym->flags & FABS) == 0) - error("align expression is not an absolute expression"); - if ((al = sym->value) == 0) - return; - - al--; - curpc = cursec->curpc; - pc = curpc+al & ~al; - - for (al = pc - curpc; al > 0; --al) - emit((char []) {0}, 1); -} - -void -end(Op *op, Node **args) -{ - endpass = 1; -} - -void -include(Op *op, Node **args) -{ - addinput(args[0]->sym->name.buf); -} diff --git a/as/main.c b/as/main.c @@ -1,138 +0,0 @@ -static char sccsid[] = "@(#) ./as/main.c"; - -#include <ctype.h> -#include <setjmp.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "../inc/scc.h" -#include "../inc/arg.h" -#include "as.h" - -char *argv0; -char *outfile, *infile; -int endpass; - - -static void -cleanup(void) -{ - if (outfile) - remove(outfile); -} - -static int -cmp(const void *f1, const void *f2) -{ - const Ins *ins = f2; - const char *s = f1; - int d; - - if ((d = *s - *ins->str) != 0) - return d; - - return strcmp(s, ins->str); -} - -static void -as(char *text, char *xargs) -{ - int c; - char *p; - Ins *ins; - Op *op, *lim; - Node **args; - - for (p = text; c = *p; ++p) - *p = toupper(c); - - ins = bsearch(text, instab, nr_ins, sizeof(Ins), cmp); - if (!ins) { - error("invalid instruction '%s'", text); - return; - } - - args = getargs(xargs); - lim = &optab[ins->end]; - for (op = &optab[ins->begin]; op < lim; ++op) { - if (match(op, args)) - break; - } - if (op == lim) { - error("invalid operands for '%s'", text); - return; - } - (*op->format)(op, args); -} - -static int -dopass(char *fname) -{ - struct line line; - FILE *fp; - extern int nerrors; - extern jmp_buf recover; - - addinput(fname); - cleansecs(); - - endpass = 0; - setjmp(recover); - while (!endpass && nextline(fp, &line)) { - linesym = NULL; - - if (line.label) - linesym = deflabel(line.label); - - if (line.op) - as(line.op, line.args); - else if (line.args) - error("arguments without an opcode"); - } - - return nerrors == 0; -} - -static void -usage(void) -{ - fputs("usage: as [-o outfile] filename ...\n", stderr); - exit(1); -} - -int -main(int argc, char *argv[]) -{ - char **p; - - outfile = "a.out"; - - ARGBEGIN { - case 'o': - outfile = EARGF(usage()); - break; - default: - usage(); - } ARGEND - - if (argc == 0) - usage(); - - atexit(cleanup); - iarch(); - isecs(); - - for (pass = 1; pass <= 2; pass++) { - for (p = argv; infile = *p; ++p) { - if (!dopass(infile)) - return 1; - } - if (pass == 1) - killtmp(); - } - writeout(outfile); - outfile = NULL; - - return 0; -} diff --git a/as/myro.c b/as/myro.c @@ -1,204 +0,0 @@ -static char sccsid[] = "@(#) ./as/myro.c"; - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "../inc/scc.h" -#include "../inc/myro.h" -#include "as.h" - -#define FORMAT "z80-scc" - -static Reloc *relocs; -static size_t relcap, relsiz; - -static size_t -writestrings(FILE *fp) -{ - int type; - size_t off = 0; - size_t len; - Symbol *sym; - Section *sp; - String *str; - - fwrite(FORMAT, sizeof(FORMAT), 1, fp); - off = sizeof(FORMAT); - - for (sym = symlist; sym; sym = sym->next) { - if (sym->flags & FREG) - continue; - str = &sym->name; - len = strlen(str->buf) + 1; - fwrite(str->buf, len, 1, fp); - str->offset = off; - off += len; - } - - return off; -} - -static unsigned -getsecflags(Section *sp) -{ - unsigned flags = 0; - - if (sp->flags & SREAD) - flags |= MYROSEC_READ; - if (sp->flags & SWRITE) - flags |= MYROSEC_WRITE; - if (sp->flags & SFILE) - flags |= MYROSEC_FILE; - if (sp->flags & SEXEC) - flags |= MYROSEC_EXEC; - if (sp->flags & SLOAD) - flags |= MYROSEC_LOAD; - if (sp->flags & SABS) - flags |= MYROSEC_ABS; - return flags; -} - -static size_t -writesections(FILE *fp) -{ - Section *sp; - size_t off = 0; - struct myrosect sect; - unsigned id = 0;; - - for (sp = seclist; sp; sp = sp->next) { - if (id == MYROMAXSEC) - die("too many sections for a myro file"); - sp->id = id++; - sect.name = sp->sym->name.offset; - sect.flags = getsecflags(sp); - sect.fill = sp->fill; - sect.aligment = sp->aligment; - sect.offset = off; - sect.len = sp->max - sp->base; - off += wrmyrosec(fp, &sect); - } - - return off; -} - -static unsigned -getsymflags(Symbol *sym) -{ - unsigned flags = 0; - - if (sym->flags & FCOMMON) - flags |= MYROSYM_COMMON; - if (sym->flags & FEXTERN) - flags |= MYROSYM_EXTERN; - if (!(sym->flags & FDEF)) - flags |= MYROSYM_UNDEF; - return flags; -} - -static size_t -writesymbols(FILE *fp) -{ - Symbol *sym; - size_t off = 0; - struct myrosym symbol; - - for (sym = symlist; sym; sym = sym->next) { - if (sym->flags & (FREG|FSECT)) - continue; - symbol.name = sym->name.offset; - symbol.type = -1; - symbol.section = sym->section->id; - symbol.flags = getsymflags(sym); - symbol.offset = sym->value; - symbol.len = sym->size; - off += wrmyrosym(fp, &symbol); - } - - return off; -} - -static size_t -writerelocs(FILE *fp) -{ - Reloc *bp, *lim; - size_t off = 0; - struct myrorel reloc; - - lim = &relocs[relsiz]; - for (bp = relocs; bp < lim; ++bp) { - reloc.id = 0; - reloc.flags = bp->flags; - reloc.size = bp->size; - reloc.nbits = bp->nbits; - reloc.shift = bp->shift; - reloc.offset = bp->offset; - off += wrmyrorel(fp, &reloc); - } - return off; -} - -static void -writedata(FILE *fp) -{ - Section *sp; - - for (sp = seclist; sp; sp = sp->next) { - if (!sp->mem) - continue; - fwrite(sp->mem, sp->max - sp->base, 1, fp); - } -} - -void -writeout(char *name) -{ - FILE *fp; - struct myrohdr hdr = { .magic = MYROMAGIC }; - - if ((fp = fopen(name, "wb")) == NULL) - die("error opening output file '%s'\n", name); - - wrmyrohdr(fp, &hdr); - hdr.strsize = writestrings(fp); - hdr.secsize = writesections(fp); - hdr.symsize = writesymbols(fp); - hdr.relsize = writerelocs(fp); - writedata(fp); - - fseek(fp, 0, SEEK_SET); - wrmyrohdr(fp, &hdr); - - if (fclose(fp)) - die("error writing the output file"); -} - -void -reloc(Symbol *sym, - unsigned flags, unsigned size, unsigned nbits, unsigned shift) -{ - size_t tmp; - Reloc *p; - - if (pass == 1) - return; - - if (relcap == relsiz) { - tmp = ((relcap + 1) * 3) / 2; - if ((p = realloc(relocs, tmp * sizeof(Reloc))) == NULL) { - tmp = relcap + 1; - p = xrealloc(relocs, tmp * sizeof(Reloc)); - } - relcap = tmp; - relocs = p; - } - - p = &relocs[relsiz++]; - p->sym = sym; - p->flags = flags; - p->size = size; - p->nbits = nbits; - p->shift = shift; - p->offset = cursec->pc - cursec->base; -} diff --git a/as/parser.c b/as/parser.c @@ -1,482 +0,0 @@ -static char sccsid[] = "@(#) ./as/parser.c"; -#include <assert.h> -#include <ctype.h> -#include <errno.h> -#include <limits.h> -#include <setjmp.h> -#include <stdarg.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include <cstd.h> -#include "../inc/scc.h" -#include "as.h" - -#define NARGS 20 -#define NR_INPUTS 10 -#define MAXLINE 100 - -struct input { - char *fname; - unsigned lineno; - FILE *fp; -}; - -int nerrors; -jmp_buf recover; -char yytext[INTIDENTSIZ+1]; -int yytoken; -size_t yylen; -union yylval yylval; - -static char *textp, *endp; -static int regmode; -static unsigned lineno; -static struct input inputs[NR_INPUTS], *isp = inputs; - -static int -follow(int expect1, int expect2, int ifyes1, int ifyes2, int ifno) -{ - int c; - - if ((c = *++textp) == expect1) - return ifyes1; - if (c == expect2) - return ifyes2; - --textp; - return ifno; -} - -static void -tok2str(void) -{ - if ((yylen = endp - textp) > INTIDENTSIZ) { - error("token too big"); - yylen = INTIDENTSIZ; - } - memcpy(yytext, textp, yylen); - yytext[yylen] = '\0'; - textp = endp; -} - -static int -iden(void) -{ - int c; - char *p; - - for ( ; c = *endp; ++endp) { - if (isalnum(c)) - continue; - switch (c) { - case '\'': - case '_': - case '-': - case '.': - case '$': - continue; - default: - goto out_loop; - } - } - -out_loop: - tok2str(); - yylval.sym = lookup(yytext); - - return (yylval.sym->flags & FREG) ? REG : IDEN; -} - -static int -number(void) -{ - int c, base = 10; - char *p; - TUINT n; - - if (*endp == '0') { - base = 8; - ++endp; - if (*endp == 'x') { - base = 16; - ++endp; - } - } - for (n = 0; (c = *endp) && isxdigit(c); n += c) { - n *= base; - c -= '0'; - if (n >= TUINT_MAX - c*base) - error("overflow in number"); - endp++; - } - tok2str(); - yylval.sym = tmpsym(n); - - return NUMBER; -} - -static int -character(void) -{ - int c; - char *p; - - while (*endp != '\'') - ++endp; - return NUMBER; -} - -static int -string(void) -{ - int c; - size_t l; - char *s; - Symbol *sym = tmpsym(0); - - for (++endp; *endp != '"'; ++endp) - ; - ++endp; - tok2str(); - yylval.sym = sym; - /* FIXME: this memory is not freed ever */ - l = yylen-2; - s = memcpy(xmalloc(l+1), yytext+1, l); - s[l] = '\0'; - sym->name.buf = s; - - return STRING; -} - -static int -operator(void) -{ - int c; - - ++endp; - if ((c = *textp) == '>') - c = follow('=', '>', LE, SHL, '>'); - else if (c == '<') - c = follow('=', '<', GE, SHR, '>'); - tok2str(); - - return c; -} - -int -next(void) -{ - int c; - - while (isspace(*textp)) - ++textp; - - endp = textp; - - switch (c = *textp) { - case '\0': - strcpy(yytext, "EOS"); - yylen = 3; - c = EOS; - break; - case '"': - c = string(); - break; - case '\'': - c = character(); - break; - case '%': - c = (regmode ? iden : operator)(); - break; - case '_': - c = iden(); - break; - default: - if (isdigit(c)) - c = number(); - else if (isalpha(c)) - c = iden(); - else - c = operator(); - break; - } - return yytoken = c; -} - -void -expect(int token) -{ - if (yytoken != token) - unexpected(); - next(); -} - -void -unexpected(void) -{ - error("unexpected '%s'", yytext); -} - -void -error(char *msg, ...) -{ - va_list va; - struct input *ip; - - assert(isp > inputs); - ip = &isp[-1]; - - va_start(va, msg); - fprintf(stderr, "as:%s:%u: ", ip->fname, ip->lineno); - vfprintf(stderr, msg, va); - putc('\n', stderr); - nerrors++; - va_end(va); - - if (nerrors == 10) - die("as: too many errors"); - longjmp(recover, 1); -} - -Node * -getreg(void) -{ - Node *np; - - np = node(REG, NULL, NULL); - np->sym = yylval.sym; - np->addr = AREG; - expect(REG); - return np; -} - -void -regctx(int mode) -{ - regmode = mode; -} - -Node * -operand(char **strp) -{ - int imm = 0; - Node *np; - - textp = *strp; - regctx(1); - switch (next()) { - case EOS: - np = NULL; - break; - case REG: - np = getreg(); - break; - case STRING: - np = node(yytoken, NULL, NULL); - np->sym = yylval.sym; - np->addr = ASTR; - next(); - break; - case '$': - next(); - imm = 1; - default: - if (!imm) { - np = moperand(); - } else { - np = expr(); - np->addr = AIMM; - } - } - if (yytoken != ',' && yytoken != EOS) - error("trailing characters in expression '%s'", textp); - *strp = endp; - - return np; -} - -Node ** -getargs(char *s) -{ - Node **ap; - static Node *args[NARGS]; - - if (!s) - return NULL; - - for (ap = args; ap < &args[NARGS-1]; ++ap) { - if ((*ap = operand(&s)) == NULL) - return args; - } - error("too many arguments in one instruction"); -} - -static char * -field(char **oldp, size_t *siz) -{ - char *s, *t, *begin; - size_t n; - - if ((begin = *oldp) == NULL) - return NULL; - - for (s = begin; isspace(*s) && *s != '\t'; ++s) - ; - if (*s == '\0' || *s == '/' || *s == ';') { - *s = '\0'; - return *oldp = NULL; - } - - for (t = s; *t && *t != '\t'; ++t) - ; - if (*t == '\t') - *t++ = '\0'; - *siz -= begin - t; - *oldp = t; - - while (t >= s && isspace(*t)) - *t-- = '\0'; - return (*s != '\0') ? s : NULL; -} - -static int -validlabel(char *name) -{ - int c; - - while ((c = *name++) != '\0') { - if (isalnum(c)) - continue; - switch (c) { - case '_': - case '-': - case '.': - case '$': - continue; - case ':': - if (*name != '\0') - return 0; - *--name = '\0'; - continue; - default: - return 0; - } - } - return 1; -} - -static int -extract(char *s, size_t len, struct line *lp) -{ - int r = 0; - - if (lp->label = field(&s, &len)) - r++; - if (lp->op = field(&s, &len)) - r++; - if (lp->args = field(&s, &len)) - r++; - - if (s && *s && *s != '/') - error("trailing characters at the end of the line"); - if (lp->label && !validlabel(lp->label)) - error("incorrect label name '%s'", lp->label); - - return r; -} - -static void -comment(FILE *fp) -{ - int c; - - while ((c = getc(fp)) != EOF) { - if (c != '*') - continue; - if ((c = getc(fp)) == '/') - return; - ungetc(c, fp); - } -} - -static size_t -getline(FILE *fp, char buff[MAXLINE]) -{ - int c; - char *bp; - - for (bp = buff; (c = getc(fp)) != EOF; *bp++ = c) { - if (c == '\n') - break; - if (c == '/') { - if ((c = getc(fp)) != '*') { - ungetc(c, fp); - c = '/'; - } else { - comment(fp); - c = ' '; - } - } else if (c > UCHAR_MAX) { - error("invalid character '%x'", c); - } - if (bp == &buff[MAXLINE-1]) - error("line too long"); - } - *bp = '\0'; - - return bp - buff; -} - -int -nextline(FILE *fp, struct line *lp) -{ - struct input *ip; - size_t n; - static char buff[MAXLINE]; - - assert(isp > inputs); -repeat: - if (isp == inputs) - return 0; - ip = &isp[-1]; - if (feof(ip->fp)) { - delinput(); - goto repeat; - } - n = getline(ip->fp, buff); - if (++ip->lineno == 0) - die("as: %s: file too long", infile); - if (n == 0) - goto repeat; - if (extract(buff, n, lp) == 0) - goto repeat; - return 1; -} - -void -addinput(char *fname) -{ - FILE *fp; - - if (isp == &inputs[NR_INPUTS]) - die("as: too many included files"); - if ((fp = fopen(fname, "r")) == NULL) - die("as: %s: %s", fname, strerror(errno)); - isp->fname = xstrdup(fname); - isp->fp = fp; - isp->lineno = 0; - ++isp; -} - -int -delinput(void) -{ - if (isp == inputs) - return EOF; - --isp; - if (fclose(isp->fp) == EOF) - die("as: %s: %s", isp->fname, strerror(errno)); - free(isp->fname); - return 0; -} diff --git a/as/symbol.c b/as/symbol.c @@ -1,291 +0,0 @@ -static char sccsid[] = "@(#) ./as/symbol.c"; - -#include <ctype.h> -#include <stdio.h> -#include <stdint.h> -#include <string.h> - -#include "../inc/scc.h" -#include "as.h" - -#define HASHSIZ 64 -#define NALLOC 10 - -Section *cursec, *seclist; -Section *sabs, *sbss, *sdata, *stext; -Symbol *linesym, *symlist; -int pass; - -static Symbol *hashtbl[HASHSIZ], *symlast; -static Alloc *tmpalloc; - - -#ifndef NDEBUG -void -dumpstab(char *msg) -{ - Symbol **bp, *sym; - - fprintf(stderr, "%s\n", msg); - for (bp = hashtbl; bp < &hashtbl[HASHSIZ]; ++bp) { - if (*bp == NULL) - continue; - - fprintf(stderr, "[%d]", (int) (bp - hashtbl)); - for (sym = *bp; sym; sym = sym->hash) { - fprintf(stderr, " -> %s:%0X:%0X", - sym->name.buf, sym->flags, sym->value); - } - putc('\n', stderr); - } -} -#endif - -Symbol * -lookup(char *name) -{ - unsigned h; - Symbol *sym, **list; - int c, symtype; - char *t, *s; - - h = 0; - for (s = name; c = *s; ++s) - h = h*33 ^ c; - h &= HASHSIZ-1; - - c = toupper(*name); - list = &hashtbl[h]; - for (sym = *list; sym; sym = sym->hash) { - t = sym->name.buf; - if (c == toupper(*t) && !casecmp(t, name)) - return sym; - } - - sym = xmalloc(sizeof(*sym)); - sym->name = newstring(name); - sym->flags = 0; - sym->size = sym->value = 0; - sym->section = cursec; - sym->hash = *list; - sym->next = NULL; - - *list = sym; - if (symlast) - symlast->next = sym; - symlast = sym; - if (!symlist) - symlist = sym; - - return sym; -} - -Symbol * -deflabel(char *name) -{ - static Symbol *cursym; - Symbol *sym; - char label[MAXSYM+1]; - - if (*name == '.') { - int r; - - if (!cursym) { - error("local label '%s' without global label", name); - return NULL; - } - r = snprintf(label, sizeof(label), - "%s%s", - cursym->name.buf, name); - if (r == sizeof(label)) { - error("local label '%s' in '%s' produces too long symbol", - name, cursym->name.buf); - return NULL; - } - name = label; - } - - sym = lookup(name); - if (pass == 1 && (sym->flags & FDEF)) - error("redefinition of label '%s'", name); - if (cursec->flags & SABS) - sym->flags |= FABS; - sym->flags |= FDEF; - sym->value = cursec->curpc; - sym->section = cursec; - - if (*name != '.') - cursym = sym; - return sym; -} - -int -toobig(Node *np, int type) -{ - /* TODO */ - return 0; -} - -static void -incpc(int siz) -{ - TUINT pc, curpc; - - pc = cursec->pc; - curpc = cursec->curpc; - - cursec->curpc += siz; - cursec->pc += siz; - - if (pass == 2) - return; - - if (cursec->pc > cursec->max) - cursec->max = cursec->pc; - - if (pc > cursec->pc || - curpc > cursec->curpc || - cursec->curpc > maxaddr || - cursec->pc > maxaddr) { - die("as: address overflow in section '%s'"); - } -} - -static int -secflags(char *attr) -{ - int c, flags; - - if (!attr) - return 0; - - for (flags = 0; c = *attr++; ) { - switch (c) { - case 'w': - flags |= SWRITE; - break; - case 'r': - flags |= SREAD; - break; - case 'x': - flags |= SEXEC; - break; - case 'f': - flags |= SFILE; - break; - case 'l': - flags |= SLOAD; - break; - case 'a': - flags |= SABS; - break; - } - } - - return flags; -} - -Section * -setsec(char *name, char *attr) -{ - Section *sec; - Symbol *sym; - - cursec = NULL; - sym = lookup(name); - if (sym->flags & ~FSECT) - error("invalid section name '%s'", name); - - if ((sec = sym->section) == NULL) { - sec = xmalloc(sizeof(*sec)); - sec->mem = NULL; - sec->sym = sym; - sec->base = sec->max = sec->pc = sec->curpc = 0; - sec->next = seclist; - sec->flags = 0; - sec->fill = 0; - sec->aligment = 0; - sec->next = seclist; - seclist = sec; - - sym->section = sec; - sym->flags = FSECT; - } - sec->flags |= secflags(attr); - - return cursec = sec; -} - -void -isecs(void) -{ - sabs = setsec(".abs", "rwx"); - sbss = setsec(".bss", "rwf"); - sdata = setsec(".data", "rw"); - stext = setsec(".text", "rx"); -} - -void -cleansecs(void) -{ - Section *sec; - TUINT siz; - - for (sec = seclist; sec; sec = sec->next) { - sec->curpc = sec->pc = sec->base; - if (pass == 1 || sec->flags & SFILE) - continue; - - siz = sec->max - sec->base; - if (siz > SIZE_MAX) - die("as: out of memory"); - sec->mem = xmalloc(sec->max - sec->base); - } - cursec = stext; -} - -void -emit(char *bytes, int n) -{ - if (cursec->mem) { - size_t len = cursec->pc - cursec->base; - memcpy(&cursec->mem[len], bytes, n); - } - incpc(n); -} - -Symbol * -tmpsym(TUINT val) -{ - Symbol *sym; - - if (!tmpalloc) - tmpalloc = alloc(sizeof(*sym), NALLOC); - sym = new(tmpalloc); - sym->value = val; - sym->section = NULL; - sym->flags = FABS; - - return sym; -} - -void -killtmp(void) -{ - if (!tmpalloc) - return; - dealloc(tmpalloc); - tmpalloc = NULL; -} - -String -newstring(char *s) -{ - size_t len = strlen(s) + 1; - String str; - - str.offset = 0; - str.buf = xmalloc(len); - memcpy(str.buf, s, len); - return str; -} diff --git a/as/target/amd64.mk b/as/target/amd64.mk @@ -1,8 +0,0 @@ - -AMD64_OBJ = $(OBJ) target/x86/amd64tbl.o target/x86/amd64.o target/x86/ins.o - -target/x86/amd64tbl.c: gentbl.awk target/x86/x86.dat target/x86/rules.dat - ./gentbl.sh -f x86 -c amd64 - -$(LIBEXEC)/as-amd64: $(AMD64_OBJ) - $(CC) $(SCC_LDFLAGS) $(AMD64_OBJ) -lscc -o $@ diff --git a/as/target/i286.mk b/as/target/i286.mk @@ -1,8 +0,0 @@ - -I286_OBJ = $(OBJ) target/x86/i286tbl.o target/x86/i286.o target/x86/ins.o - -target/x86/i286tbl.c: gentbl.awk target/x86/x86.dat target/x86/rules.dat - ./gentbl.sh -f x86 -c i286 - -$(LIBEXEC)/as-i286: $(I286_OBJ) - $(CC) $(SCC_LDFLAGS) $(I286_OBJ) -lscc -o $@ diff --git a/as/target/i386.mk b/as/target/i386.mk @@ -1,8 +0,0 @@ - -I386_OBJ = $(OBJ) target/x86/i386tbl.o target/x86/i386.o target/x86/ins.o - -target/x86/i386tbl.c: gentbl.awk target/x86/x86.dat target/x86/rules.dat - ./gentbl.sh -f x86 -c i386 - -$(LIBEXEC)/as-i386: $(I386_OBJ) - $(CC) $(SCC_LDFLAGS) $(I386_OBJ) -lscc -o $@ diff --git a/as/target/x80/ins.c b/as/target/x80/ins.c @@ -1,600 +0,0 @@ -static char sccsid[] = "@(#) ./as/target/x80/ins.c"; - -#include <stdlib.h> -#include <string.h> - -#include "../../../inc/scc.h" -#include "../../as.h" -#include "proc.h" - -/* - * This implementation is based in: - * - Zilog Z80 CPU Specifications by Sean Young - * - Decoding Z80 opcodes - of use to disassembler and emulator - * writers - by Cristian Dinu. - */ - -static int -getclass(Node *np) -{ - if (np->addr != AREG) - return 0; - - switch (np->sym->value) { - case AREG_C: - return RCLASS | PCLASS | QCLASS | CCCLASS | SSCLASS; - case AREG_A: - case AREG_B: - case AREG_D: - case AREG_E: - return RCLASS | PCLASS | QCLASS; - case AREG_H: - case AREG_L: - return RCLASS; - case AREG_IXL: - case AREG_IXH: - return PCLASS; - case AREG_IYL: - case AREG_IYH: - return QCLASS; - case AREG_HL: - return DDCLASS | QQCLASS; - case AREG_BC: - case AREG_DE: - return DDCLASS | QQCLASS | PPCLASS | RRCLASS; - case AREG_SP: - return DDCLASS | PPCLASS | RRCLASS; - case AREG_AF: - return QQCLASS; - case AREG_IX: - return PPCLASS; - case AREG_IY: - return RRCLASS; - case AREG_PO: - case AREG_PE: - case AREG_P: - case AREG_M: - return CCCLASS; - case AREG_NZ: - case AREG_Z: - case AREG_NC: - return CCCLASS | SSCLASS; - default: - return 0; - } -} - -int -match(Op *op, Node **args) -{ - unsigned char *p; - int arg, class, rep, opt; - Node *np; - - if (!op->args) - return args == NULL; - - opt = rep = 0; - for (p = op->args; arg = *p; ++p) { - if (rep) - --p; - if ((np = *args++) == NULL) - return (rep|opt) != 0; - - switch (arg) { - case AOPT: - opt = 1; - break; - case AREP: - rep = 1; - break; - case AINDER_C: - arg = AREG_C; - goto indirect; - case AINDER_HL: - arg = AREG_HL; - goto indirect; - case AINDER_DE: - arg = AREG_DE; - goto indirect; - case AINDER_BC: - arg = AREG_BC; - goto indirect; - case AINDER_IX: - arg = AREG_IX; - goto indirect; - case AINDER_IY: - arg = AREG_IY; - goto indirect; - case AINDER_SP: - arg = AREG_SP; - indirect: - if (np->addr != AINDIR) - return 0; - np = np->left; - case AREG_A: - case AREG_I: - case AREG_R: - case AREG_F: - case AREG_HL: - case AREG_BC: - case AREG_DE: - case AREG_IY: - case AREG_IX: - case AREG_SP: - case AREG_AF: - case AREG_AF_: - if (np->addr != AREG || np->sym->value != arg) - return 0; - break; - case AREG_RCLASS: - class = RCLASS; - goto check_class; - case AREG_PCLASS: - class = PCLASS; - goto check_class; - case AREG_QCLASS: - class = QCLASS; - goto check_class; - case AREG_QQCLASS: - class = QQCLASS; - goto check_class; - case AREG_PPCLASS: - class = PPCLASS; - goto check_class; - case AREG_RRCLASS: - class = RRCLASS; - goto check_class; - case AREG_CCCLASS: - class = CCCLASS; - goto check_class; - case AREG_SSCLASS: - class = SSCLASS; - goto check_class; - case AREG_DDCLASS: - class = DDCLASS; - check_class: - if ((getclass(np) & class) == 0) - return 0; - break; - case AINDEX_IY: - arg = AREG_IY; - goto index_address; - case AINDEX_IX: - arg = AREG_IX; - index_address: - if (np->addr != AINDEX) - return 0; - if (np->left->left->sym->value != arg) - return 0; - if (toobig(np, arg)) - error("overflow in index"); - break; - case ARST: - if (np->addr != AIMM) - return 0; - if ((np->sym->value & ~0x38) != 0) - return 0; - break; - case AZERO: - case AIMM3: - case AIMM8: - case AIMM16: - case AIMM32: - case AIMM64: - if (np->addr != AIMM) - return 0; - if (toobig(np, arg)) - error("overflow in immediate operand"); - break; - case ASYM: - if (np->addr != AIMM || np->op != IDEN) - return 0; - break; - case ADIRECT: - case ASTR: - if (np->addr != arg) - return 0; - break; - default: - abort(); - } - } - - return *args == NULL; -} - -/* - * (expr) -> ADIRECT - * (REG) -> AINDIR - * (REG + expr) -> AINDEX - * (REG - expr) -> AINDEX - * expr (REG) -> AINDEX - */ -Node * -moperand(void) -{ - int op; - Node *np, *dir, *off, *reg; - - dir = off = reg = NULL; - if (accept('(')) { - if (yytoken != REG) { - dir = expr(); - } else { - reg = getreg(); - switch (yytoken) { - case '+': - case '-': - off = expr(); - case ')': - break; - default: - unexpected(); - } - } - } else { - off = expr(); - expect('('); - reg = getreg(); - } - expect(')'); - - if (dir) { - op = ADIRECT; - np = dir; - } else if (off) { - np = node(AREG_OFF, reg, off); - op = AINDEX; - } else { - np = reg; - op = AINDIR; - } - np = node(op, np, NULL); - np->addr = op; - return np; -} - -static int -reg2int(Node *np) -{ - switch (np->sym->value) { - case AREG_F: - case AREG_B: return 0; - case AREG_C: return 1; - case AREG_D: return 2; - case AREG_E: return 3; - case AREG_IXH: - case AREG_IYH: - case AREG_H: return 4; - case AREG_IXL: - case AREG_IYL: - case AREG_L: return 5; - case AREG_A: return 7; - case AREG_BC: return 0; - case AREG_DE: return 1; - case AREG_HL: - case AREG_IX: - case AREG_IY: return 2; - case AREG_AF: - case AREG_SP: return 3; - default: abort(); - } -} - -static int -cc2int(Node *np) -{ - switch (np->sym->value) { - case AREG_NZ: return 0; - case AREG_Z: return 1; - case AREG_NC: return 2; - case AREG_C: return 3; - case AREG_PO: return 4; - case AREG_PE: return 5; - case AREG_P: return 6; - case AREG_M: return 7; - default: abort(); - } -} - -static int -ss2int(Node *np) -{ - switch (np->sym->value) { - case AREG_NZ: return 4; - case AREG_Z: return 5; - case AREG_NC: return 6; - case AREG_C: return 7; - default: abort(); - } -} - -void -dir(Op *op, Node **args) -{ - Node *imm; - unsigned char buf[4]; - unsigned val; - int n = op->size; - - imm = (args[1]->addr == ADIRECT) ? args[1] : args[0]; - imm = imm->left; - memcpy(buf, op->bytes, n); - val = imm->sym->value; - buf[n-1] = val >> 8; - buf[n-2] = val; - emit(buf, n); -} - -void -ld8(Op *op, Node **args) -{ - Node *par1 = args[0], *par2 = args[1]; - int n = op->size, i = n;; - unsigned regval = 0; - unsigned char buf[4]; - - memcpy(buf, op->bytes, n); - - if (par1->addr == AREG) - regval |= reg2int(par1) << 3; - if (par2->addr == AREG) - regval |= reg2int(par2); - else if (par2->addr == AIMM) - buf[--i] = par2->sym->value; - - buf[--i] |= regval; - emit(buf, n); -} - -void -alu16(Op *op, Node **args) -{ - Node *par; - int n = op->size; - unsigned val; - unsigned char buf[4]; - - par = (args[1]) ? args[1] : args[0]; - val = reg2int(par); - memcpy(buf, op->bytes, n); - buf[n-1] |= val << 4; - emit(buf, n); -} - -void -ld16(Op *op, Node **args) -{ - Node *dst, *src, *tmp; - int n = op->size; - unsigned val; - unsigned char buf[4]; - - dst = args[0]; - src = args[1]; - if (!src) { - alu16(op, args); - return; - } - - if (dst->addr != AREG) { - tmp = src; - src = dst; - dst = tmp; - } - - memcpy(buf, op->bytes, n); - if (src->addr == ADIRECT) - src = src->left; - val = src->sym->value; - buf[n-1] = val >> 8; - buf[n-2] = val; - buf[n-3] |= reg2int(dst) << 4; - emit(buf, n); -} - -void -alu8(Op *op, Node **args) -{ - Node *par = args[1]; - unsigned char buf[4]; - int n = op->size, shift; - unsigned val; - - if (args[1]) { - shift = 0; - par = args[1]; - } else { - shift = 3; - par = args[0]; - } - - switch (par->addr) { - case AIMM: - val = par->sym->value; - break; - case AREG: - val = reg2int(par) << shift; - break; - case AINDEX: - val = par->left->right->sym->value; - break; - case AINDIR: - val = 0; - break; - default: - abort(); - } - - memcpy(buf, op->bytes, n); - buf[n-1] |= val; - emit(buf, n); -} - -void -idx(Op *op, Node **args) -{ - Node *tmp, *idx, *imm, *reg; - unsigned char buf[4]; - int n = op->size, i = n, shift = 0; - - imm = reg = NULL; - if (args[0]->addr != AINDEX) { - shift = 3; - tmp = args[0]; - args[0] = args[1]; - args[1] = tmp; - } - idx = args[0]->left->right; - - if (args[1]->addr == AREG) - reg = args[1]; - else - imm = args[1]; - - memcpy(buf, op->bytes, n); - - if (imm) - buf[--i] = imm->sym->value; - buf[--i] = idx->sym->value; - if (reg) - buf[--i] |= reg2int(reg) << shift; - - emit(buf, n); -} - -void -inout(Op *op, Node **args) -{ - Node *port, *value; - unsigned val; - int n = op->size; - unsigned char buf[5]; - - port = args[0]; - value = args[1]; - if (port->addr != ADIRECT && port->addr != AINDIR) { - value = port; - port = args[1]; - } - - if (port->addr == ADIRECT) - val = port->left->sym->value; - else if (value->addr == AREG) - val = reg2int(value) << 3; - else - val = 0; - - memcpy(buf, op->bytes, n); - buf[n-1] |= val; - emit(buf, n); -} - -void -rot_bit(Op *op, Node **args) -{ - Node *par = args[0]; - unsigned char buf[5]; - int n = op->size; - unsigned val, npar = 0; - - memcpy(buf, op->bytes, n); - - par = args[0]; - if (par->addr == AIMM) { - buf[n-1] |= par->sym->value << 3; - par = args[npar = 1]; - } - - switch (par->addr) { - case AINDEX: - val = par->left->right->sym->value; - buf[n-2] = val; - par = args[npar+1]; - if (!par) - break; - case AREG: - val = reg2int(par); - buf[n-1] |= val; - case AINDIR: - break; - default: - abort(); - } - - emit(buf, n); -} - -void -im(Op *op, Node **args) -{ - unsigned val = args[0]->sym->value; - unsigned char buf[4]; - int n = op->size; - - if (val > 0) - ++val; - - memcpy(buf, op->bytes, n); - buf[n-1] |= val << 3; - emit(buf, n); -} - -void -branch(int relative, Op *op, Node **args) -{ - unsigned char buf[4]; - Node *flag, *imm; - int n = op->size, i = n; - unsigned val; - int (*fun)(Node *); - - flag = imm = NULL; - if (args[0]->addr == AREG) { - flag = args[0]; - imm = args[1]; - } else if (args[0]->addr == AIMM) { - imm = args[0]; - } - memcpy(buf, op->bytes, n); - - if (imm) { - val = imm->sym->value; - if (!relative) - buf[--i] = val >> 8; - else - val -= cursec->curpc - 2; - buf[--i] = val; - - } - if (flag) { - fun = (relative) ? ss2int : cc2int; - buf[--i] |= (*fun)(flag) << 3; - } - - - emit(buf, n); -} - -void -jp(Op *op, Node **args) -{ - branch(0, op, args); -} - -void -jr(Op *op, Node **args) -{ - branch(1, op, args); -} - -void -rst(Op *op, Node **args) -{ - unsigned char buf[1]; - - buf[0] = op->bytes[0]; - buf[0] |= args[0]->sym->value; - emit(buf, 1); -} diff --git a/as/target/x80/z80.c b/as/target/x80/z80.c @@ -1,64 +0,0 @@ -static char sccsid[] = "@(#) ./as/target/x80/z80.c"; - -#include <stdlib.h> - -#include "../../../inc/scc.h" -#include "../../as.h" -#include "../x80/proc.h" - -TUINT maxaddr = 0xFFFFFFFF; -int endian = LITTLE_ENDIAN; - -void -iarch(void) -{ - static struct { - char *name; - char type; - } regs[] = { - "AF", AREG_AF, - "A", AREG_A, - "F", AREG_F, - - "BC", AREG_BC, - "B", AREG_B, - "C", AREG_C, - - "HL", AREG_HL, - "H", AREG_H, - "L", AREG_L, - - "DE", AREG_DE, - "D", AREG_D, - "E", AREG_E, - - "IX", AREG_IX, - "IXL", AREG_IXL, - "IXH", AREG_IXH, - - "IY", AREG_IY, - "IYL", AREG_IYL, - "IYH", AREG_IYH, - - "R", AREG_R, - "I", AREG_I, - "AF'", AREG_AF_, - "SP", AREG_SP, - - "NZ", AREG_NZ, - "Z", AREG_Z, - "NC", AREG_NC, - "PO", AREG_PO, - "PE", AREG_PE, - "P", AREG_P, - "M", AREG_M, - - NULL, - }, *bp; - - for (bp = regs; bp->name; ++bp) { - Symbol *sym = lookup(bp->name); - sym->flags = FREG; - sym->value = bp->type; - } -} diff --git a/as/target/x86/amd64.c b/as/target/x86/amd64.c @@ -1,12 +0,0 @@ -static char sccsid[] = "@(#) ./as/target/x86/amd64.c"; - -#include "../../../inc/scc.h" -#include "../../as.h" - -TUINT maxaddr = 0xFFFFFFFFFFFFFFFF; -int endian = LITTLE_ENDIAN; - -void -iarch(void) -{ -} diff --git a/as/target/x86/i286.c b/as/target/x86/i286.c @@ -1,53 +0,0 @@ -static char sccsid[] = "@(#) ./as/target/x86/i286.c"; - -#include "../../../inc/scc.h" -#include "../../as.h" -#include "../x86/proc.h" - -TUINT maxaddr = 0xFFFF; -int endian = LITTLE_ENDIAN; -int left2right = 0; - -void -iarch(void) -{ - static struct { - char *name; - char type; - } regs[] = { - "CS", AREG_CS, - "DS", AREG_DS, - "SS", AREG_SS, - "ES", AREG_ES, - - "AX", AREG_AX, - "AL", AREG_AL, - "AH", AREG_AH, - - "BX", AREG_BX, - "BL", AREG_BL, - "BH", AREG_BH, - - "CX", AREG_CX, - "CL", AREG_CL, - "CH", AREG_CH, - - "DX", AREG_DX, - "DL", AREG_DL, - "DH", AREG_DH, - - "SI", AREG_SI, - "DI", AREG_DI, - - "SP", AREG_SP, - "BP", AREG_BP, - - NULL - }, *bp; - - for (bp = regs; bp->name; ++bp) { - Symbol *sym = lookup(bp->name); - sym->flags = FREG; - sym->value = bp->type; - } -} diff --git a/as/target/x86/i386.c b/as/target/x86/i386.c @@ -1,100 +0,0 @@ -static char sccsid[] = "@(#) ./as/target/x86/i386.c"; - -#include "../../../inc/scc.h" -#include "../../as.h" -#include "../x86/proc.h" - -TUINT maxaddr = 0xFFFFFFFF; -int endian = LITTLE_ENDIAN; - -void -iarch(void) -{ - static struct { - char *name; - char type; - } regs[] = { - "CS", AREG_CS, - "DS", AREG_DS, - "SS", AREG_SS, - "ES", AREG_ES, - "FS", AREG_FS, - "GS", AREG_GS, - - "AX", AREG_AX, - "AL", AREG_AL, - "AH", AREG_AH, - "EAX", AREG_EAX, - - "BC", AREG_BX, - "BL", AREG_BL, - "BH", AREG_BH, - "EBX", AREG_EBX, - - "CX", AREG_CX, - "CL", AREG_CL, - "CH", AREG_CH, - "ECX", AREG_ECX, - - "DX", AREG_DX, - "DL", AREG_DL, - "DH", AREG_DH, - "EDX", AREG_EDX, - - "SI", AREG_SI, - "ESI", AREG_ESI, - "DI", AREG_DI, - "EDI", AREG_EDI, - - "SP", AREG_SP, - "ESP", AREG_ESP, - - "BP", AREG_BP, - "EBP", AREG_EBP, - - "R0", AREG_R0, - "MM0", AREG_MM0, - "R1", AREG_R1, - "MM1", AREG_MM1, - "R2", AREG_R2, - "MM2", AREG_MM2, - "R3", AREG_R3, - "MM3", AREG_MM3, - "R4", AREG_R4, - "MM4", AREG_MM4, - "R5", AREG_R5, - "MM5", AREG_MM5, - "R6", AREG_R6, - "MM6", AREG_MM6, - "R7", AREG_R7, - "MM7", AREG_MM7, - - "XMM0", AREG_XMM0, - "XMM1", AREG_XMM1, - "XMM2", AREG_XMM2, - "XMM3", AREG_XMM3, - "XMM4", AREG_XMM4, - "XMM5", AREG_XMM5, - "XMM6", AREG_XMM6, - "XMM7", AREG_XMM7, - - "YMM0", AREG_YMM0, - "YMM1", AREG_YMM1, - "YMM2", AREG_YMM2, - "YMM3", AREG_YMM3, - "YMM4", AREG_YMM4, - "YMM5", AREG_YMM5, - "YMM6", AREG_YMM6, - "YMM7", AREG_YMM7, - - "MXCSR", AREG_MXCSR, - - NULL - }, *bp; - - for (bp = regs; bp->name; ++bp) { - Symbol *sym = lookup(bp->name); - sym->flags = FREG; - sym->value = bp->type; - } -} diff --git a/as/target/x86/ins.c b/as/target/x86/ins.c @@ -1,301 +0,0 @@ -static char sccsid[] = "@(#) ./as/target/x86/ins.c"; - -#include <stdlib.h> - -#include "../../../inc/scc.h" -#include "../../as.h" -#include "proc.h" - -#define addrbyte(mod, reg, rm) ((mod) << 6 | (reg) << 3 | (rm)) - -enum addr_mode { - MEM_MODE = 0, - MEM8_MODE = 1, - MEM16_MODE = 2, - REG_MODE = 3, -}; - -static int -getclass(Node *np) -{ - if (np->addr != AREG) - return 0; - - switch (np->sym->value) { - case AREG_AL: - case AREG_AH: - case AREG_BL: - case AREG_BH: - case AREG_CL: - case AREG_CH: - case AREG_DL: - case AREG_DH: - return R8CLASS; - - case AREG_AX: - case AREG_BX: - case AREG_CX: - case AREG_DX: - case AREG_DI: - case AREG_SI: - case AREG_SP: - case AREG_BP: - return R16CLASS; - - case AREG_CS: - case AREG_DS: - case AREG_SS: - case AREG_ES: - case AREG_FS: - case AREG_GS: - - case AREG_EFLAGS: - case AREG_CF: - case AREG_PF: - case AREG_AF: - case AREG_ZF: - case AREG_SF: - case AREG_TF: - case AREG_IF: - case AREG_DF: - case AREG_OF: - case AREG_IOPL: - case AREG_NT: - case AREG_RF: - case AREG_VM: - case AREG_AC: - case AREG_VIF: - case AREG_VIP: - case AREG_ID: - - case AREG_EAX: - case AREG_RAX: - - case AREG_EBX: - case AREG_RBX: - - case AREG_ECX: - case AREG_RCX: - - case AREG_EDX: - case AREG_RDX: - - case AREG_SIL: - case AREG_ESI: - case AREG_RSI: - case AREG_DIL: - case AREG_EDI: - case AREG_RDI: - - case AREG_SPL: - case AREG_ESP: - case AREG_RSP: - - case AREG_BPL: - case AREG_EBP: - case AREG_RBP: - - case AREG_R0: - case AREG_MM0: - case AREG_R1: - case AREG_MM1: - case AREG_R2: - case AREG_MM2: - case AREG_R3: - case AREG_MM3: - case AREG_R4: - case AREG_MM4: - case AREG_R5: - case AREG_MM5: - case AREG_R6: - case AREG_MM6: - case AREG_R7: - case AREG_MM7: - - case AREG_R8: - case AREG_R8L: - case AREG_R8W: - case AREG_R9: - case AREG_R9L: - case AREG_R9W: - case AREG_R10: - case AREG_R10L: - case AREG_R10W: - case AREG_R11: - case AREG_R11L: - case AREG_R11W: - case AREG_R12: - case AREG_R12L: - case AREG_R12W: - case AREG_R13: - case AREG_R13L: - case AREG_R13W: - case AREG_R14: - case AREG_R14L: - case AREG_R14W: - case AREG_R15: - case AREG_R15L: - case AREG_R15W: - - case AREG_XMM0: - case AREG_XMM1: - case AREG_XMM2: - case AREG_XMM3: - case AREG_XMM4: - case AREG_XMM5: - case AREG_XMM6: - case AREG_XMM7: - case AREG_XMM8: - case AREG_XMM9: - case AREG_XMM10: - case AREG_XMM11: - case AREG_XMM12: - case AREG_XMM13: - case AREG_XMM14: - case AREG_XMM15: - - case AREG_YMM0: - case AREG_YMM1: - case AREG_YMM2: - case AREG_YMM3: - case AREG_YMM4: - case AREG_YMM5: - case AREG_YMM6: - case AREG_YMM7: - case AREG_YMM8: - case AREG_YMM9: - case AREG_YMM10: - case AREG_YMM11: - case AREG_YMM12: - case AREG_YMM13: - case AREG_YMM14: - case AREG_YMM15: - - case AREG_MXCSR: - return 0; - default: - abort(); - } -} - -int -match(Op *op, Node **args) -{ - unsigned char *p; - int arg, class, rep, opt; - Node *np; - - if (!op->args) - return args == NULL; - - opt = rep = 0; - for (p = op->args; arg = *p; ++p) { - if (rep) - --p; - if ((np = *args++) == NULL) - return (rep|opt) != 0; - - switch (arg) { - case AOPT: - opt = 1; - break; - case AREP: - rep = 1; - break; - case AREG_R8CLASS: - class = R8CLASS; - goto check_class; - case AREG_R16CLASS: - class = R16CLASS; - check_class: - if ((getclass(np) & class) == 0) - return 0; - break; - case AIMM8: - case AIMM16: - case AIMM32: - case AIMM64: - if (np->addr != AIMM) - return 0; - if (toobig(np, arg)) - error("overflow in immediate operand"); - break; - case ASYM: - if (np->addr != AIMM || np->op != IDEN) - return 0; - break; - case ADIRECT: - case ASTR: - if (np->addr != arg) - return 0; - break; - default: - abort(); - } - } - - return *args == NULL; -} - -Node * -moperand(void) -{ -} - -static int -reg8toint(Node *np) -{ - switch (np->sym->value) { - case AREG_AL: return 0; - case AREG_CL: return 1; - case AREG_DL: return 2; - case AREG_BL: return 3; - case AREG_AH: return 4; - case AREG_CH: return 5; - case AREG_DH: return 6; - case AREG_BH: return 7; - default: abort(); - } -} - -void -reg8_reg8(Op *op, Node **args) -{ - int src, dst; - char buf[2]; - - src = reg8toint(args[0]); - dst = reg8toint(args[1]); - buf[0] = op->bytes[0]; - buf[1] = addrbyte(REG_MODE, src, dst); - emit(buf, 2); -} - -static int -reg16toint(Node *np) -{ - switch (np->sym->value) { - case AREG_AX: return 0; - case AREG_CX: return 1; - case AREG_DX: return 2; - case AREG_BX: return 3; - case AREG_SP: return 4; - case AREG_BP: return 5; - case AREG_SI: return 6; - case AREG_DI: return 7; - default: abort(); - } -} - -void -reg16_reg16(Op *op, Node **args) -{ - int src, dst; - char buf[2]; - - src = reg16toint(args[0]); - dst = reg16toint(args[1]); - buf[0] = op->bytes[0]; - buf[1] = addrbyte(REG_MODE, src, dst); - emit(buf, 2); -} diff --git a/as/target/z80.mk b/as/target/z80.mk @@ -1,8 +0,0 @@ - -Z80_OBJ = $(OBJ) target/x80/z80tbl.o target/x80/z80.o target/x80/ins.o - -target/x80/z80tbl.c: gentbl.awk target/x80/x80.dat target/x80/rules.dat - ./gentbl.sh -f x80 -c z80 - -$(LIBEXEC)/as-z80: $(OBJ) $(Z80_OBJ) - $(CC) $(SCC_LDFLAGS) $(Z80_OBJ) -lscc -o $@ diff --git a/cc1/Makefile b/cc1/Makefile @@ -1,32 +0,0 @@ -.POSIX: - -PROJECTDIR = .. - -include $(PROJECTDIR)/rules.mk -include $(LIBSCC)/libdep.mk - -MORECFLAGS = -I$(INCLUDE)/$(STD) - -OBJ = types.o decl.o lex.o error.o symbol.o main.o expr.o \ - code.o stmt.o cpp.o fold.o init.o builtin.o - -TARGETS = $(LIBEXEC)/cc1-amd64-sysv $(LIBEXEC)/cc1-arm64-sysv \ - $(LIBEXEC)/cc1-i386-sysv $(LIBEXEC)/cc1-z80-scc - -all: $(TARGETS) - -$(TARGETS): $(LIBDIR)/libscc.a - -dep: - $(PROJECTDIR)/mkdep.sh - -clean: - rm -f *.o - rm -f target/*/*.o - rm -f $(TARGETS) - -include target/amd64-sysv/arch.mk -include target/arm64-sysv/arch.mk -include target/i386-sysv/arch.mk -include target/z80-scc/arch.mk -include deps.mk diff --git a/cc1/builtin.c b/cc1/builtin.c @@ -1,121 +0,0 @@ -static char sccsid[] = "@(#) ./cc1/builtin.c"; - -#include <stdio.h> - -#include "../inc/scc.h" -#include "cc1.h" - -static Node * -builtin_va_arg(Symbol *sym) -{ - Node *np, *ap; - Type *tp; - - ap = assign(); - expect(','); - tp = typename(); - - if (!valid_va_list(ap->type)) { - errorp("incorrect parameters for va_arg"); - goto error; - } - if (tp == booltype || - tp == chartype || tp == uchartype || tp == schartype || - tp == shortype || tp == ushortype) { - warn("bool, char and short are promoted to int when passed through '...'"); - tp = (tp->prop & TSIGNED) ? inttype : uinttype; - } - - np = node(OBUILTIN, tp, ap, NULL); - np->sym = sym; - return np; - -error: - return constnode(zero); -} - -static Node * -builtin_va_copy(Symbol *sym) -{ - Node *np, *src, *dst; - - dst = assign(); - expect(','); - src = assign(); - - if (!valid_va_list(dst->type) || !valid_va_list(src->type)) { - errorp("incorrect parameters for va_copy"); - return constnode(zero); - } - - np = node(OBUILTIN, voidtype, dst, src); - np->sym = sym; - return np; -} - -static Node * -builtin_va_start(Symbol *sym) -{ - Node *np, *ap, *last; - Symbol **p; - Type *tp; - - ap = assign(); - expect(','); - last = assign(); - if (last->op != OSYM) - goto error; - - if (!valid_va_list(ap->type) || !(last->sym->flags&SDECLARED)) - goto error; - - for (p = curfun->u.pars; p && *p != last->sym; ++p) - ; - if (!p || *p == NULL || p[1] == NULL || p[1]->type != ellipsistype) - warn("second parameter of 'va_start' not last named argument"); - - tp = last->type; - if (tp == booltype || - tp == chartype || tp == uchartype || tp == schartype || - tp == shortype || tp == ushortype) { - warn("last parameter before '...' must not be bool, char or short"); - } - - np = node(OBUILTIN, voidtype, ap, last); - np->sym = sym; - return np; - -error: - errorp("incorrect parameters for va_start"); - return constnode(zero); -} - -static Node * -builtin_va_end(Symbol *sym) -{ - Node *ap, *np; - - ap = assign(); - - if (!valid_va_list(ap->type)) { - errorp("incorrect parameters for va_end"); - return constnode(zero); - } - - np = node(OBUILTIN, voidtype, ap, NULL); - np->sym = sym; - return np; -} - -void -ibuilts(void) -{ - struct builtin built[] = { - {"__builtin_va_arg", builtin_va_arg}, - {"__builtin_va_copy", builtin_va_copy}, - {"__builtin_va_start", builtin_va_start}, - {"__builtin_va_end", builtin_va_end}, - {NULL} - }; - builtins(built); -} diff --git a/cc1/code.c b/cc1/code.c @@ -1,550 +0,0 @@ -static char sccsid[] = "@(#) ./cc1/code.c"; -#include <ctype.h> -#include <stdio.h> -#include <stdlib.h> -#include <stdarg.h> - -#include "../inc/scc.h" -#include "cc1.h" - -static void emitbin(int, void *), - emitcast(int, void *), - emitsym(int, void *), - emitexp(int, void *), - emitsymid(int, void *), - emittext(int, void *), - emitfun(int, void *), - emitdcl(int, void *), - emitinit(int, void *), - emittype(int, void *), - emitbuilt(int, void *); - -char *optxt[] = { - [OADD] = "+", - [OSUB] = "-", - [OMUL] = "*", - [OINC] = ":i", - [ODEC] = ":d", - [OPTR] = "@", - [OMOD] = "%", - [ODIV] = "/", - [OSHL] = "l", - [OSHR] = "r", - [OLT] = "<", - [OGT] = ">", - [OGE] = "]", - [OLE] = "[", - [OEQ] = "=", - [ONE] = "!", - [OBAND] = "&", - [OBXOR] = "^", - [OBOR] = "|", - [OASSIGN] = ":", - [OA_MUL] = ":*", - [OA_DIV] = ":/", - [OA_MOD] = ":%", - [OA_ADD] = ":+", - [OA_SUB] = ":-", - [OA_SHL] = ":l", - [OA_SHR] = ":r", - [OA_AND] = ":&", - [OA_XOR] = ":^", - [OA_OR] = ":|", - [OADDR] = "'", - [OSNEG] = "_", - [ONEG] = "n", - [OCPL] = "~", - [OAND] = "a", - [OOR] = "o", - [OASK] = "?", - [OCOMMA] = ",", - [OLABEL] = "L%d\n", - [ODEFAULT] = "\tf\tL%d\n", - [OBSWITCH] = "\ts", - [OESWITCH] = "\tt\tL%d\n", - [OCASE] = "\tv\tL%d", - [OJUMP] = "\tj\tL%d\n", - [OBRANCH] = "\ty\tL%d", - [OEFUN] = "}\n", - [OELOOP] = "\tb\n", - [OBLOOP] = "\te\n", - [ORET] = "\th", - [OPAR] = "p", - [OCALL] = "c", - [OCALLE] = "z", - [OFIELD] = "." -}; - -void (*opcode[])(int, void *) = { - [OADD] = emitbin, - [OSUB] = emitbin, - [OMUL] = emitbin, - [OINC] = emitbin, - [ODEC] = emitbin, - [OPTR] = emitbin, - [OMOD] = emitbin, - [ODIV] = emitbin, - [OSHL] = emitbin, - [OSHR] = emitbin, - [OLT] = emitbin, - [OGT] = emitbin, - [OGE] = emitbin, - [OLE] = emitbin, - [OEQ] = emitbin, - [ONE] = emitbin, - [OBAND] = emitbin, - [OBXOR] = emitbin, - [OBOR] = emitbin, - [OASSIGN] = emitbin, - [OA_MUL] = emitbin, - [OA_DIV] = emitbin, - [OA_MOD] = emitbin, - [OA_ADD] = emitbin, - [OA_SUB] = emitbin, - [OA_SHL] = emitbin, - [OA_SHR] = emitbin, - [OA_AND] = emitbin, - [OA_XOR] = emitbin, - [OA_OR] = emitbin, - [OADDR] = emitbin, - [OSNEG] = emitbin, - [ONEG] = emitbin, - [OCPL] = emitbin, - [OAND] = emitbin, - [OOR] = emitbin, - [OCOMMA] = emitbin, - [OCAST] = emitcast, - [OSYM] = emitsym, - [OASK] = emitbin, - [OCOLON] = emitbin, - [OFIELD]= emitbin, - [OEXPR] = emitexp, - [OLABEL] = emitsymid, - [ODEFAULT] = emitsymid, - [OCASE] = emitsymid, - [OJUMP] = emitsymid, - [OBRANCH] = emitsymid, - [OEFUN] = emittext, - [OELOOP] = emittext, - [OBLOOP] = emittext, - [OFUN] = emitfun, - [ORET] = emittext, - [ODECL] = emitdcl, - [OBSWITCH] = emittext, - [OESWITCH] = emitsymid, - [OPAR] = emitbin, - [OCALL] = emitbin, - [OCALLE] = emitbin, - [OINIT] = emitinit, - [OBUILTIN] = emitbuilt, - [OTYP] = emittype, -}; - -static FILE *outfp; - -void -icode(void) -{ - outfp = stdout; -} - -void -freetree(Node *np) -{ - if (!np) - return; - freetree(np->left); - freetree(np->right); - free(np); -} - -static void -emitnode(Node *np) -{ - if (np) - (*opcode[np->op])(np->op, np); -} - -void -prtree(Node *np) -{ - outfp = stderr; - fputs("DBG prtree", outfp); - emitnode(np); - putc('\n', outfp); - outfp = stdout; -} - -void -emit(int op, void *arg) -{ - extern int failure; - - if (failure || onlycpp || onlyheader) - return; - (*opcode[op])(op, arg); -} - -static void -emitvar(Symbol *sym) -{ - int c; - short flags = sym->flags; - - if (flags & SLOCAL) - c = 'T'; - else if (flags & SPRIVATE) - c = 'Y'; - else if (flags & SGLOBAL) - c = 'G'; - else if (flags & SREGISTER) - c = 'R'; - else if (flags & SFIELD) - c = 'M'; - else if (flags & SEXTERN) - c = 'X'; - else - c = 'A'; - fprintf(outfp, "%c%u", c, sym->id); -} - -static void -emitconst(Node *np) -{ - Symbol *sym = np->sym; - Type *tp = np->type; - TUINT u; - - switch (tp->op) { - case PTR: - case INT: - case ENUM: - u = (tp->prop & TSIGNED) ? (TUINT) sym->u.i : sym->u.u; - fprintf(outfp, - "#%c%llX", - np->type->letter, - (long long) u & ones(tp->size)); - break; - default: - abort(); - } -} - -static void -emitsym(int op, void *arg) -{ - Node *np = arg; - - if ((np->sym->flags & SINITLST) == 0) { - /* - * When we have a compound literal we are going - * to call to emitnode for every element of it, - * and it means that we will have two '\t' - * for the first element - */ - putc('\t', outfp); - } - (np->flags & NCONST) ? emitconst(np) : emitvar(np->sym); -} - -static void -emitletter(Type *tp) -{ - int letter; - - letter = (tp->prop&TELLIPSIS) ? 'E' : tp->letter; - putc(letter, outfp); - switch (tp->op) { - case ARY: - case STRUCT: - case UNION: - fprintf(outfp, "%u", tp->id); - } -} - -static void -emittype(int op, void *arg) -{ - TINT n; - Symbol **sp; - char *tag; - Type *tp = arg; - - if (!(tp->prop & TDEFINED)) - return; - - switch (tp->op) { - case ARY: - emitletter(tp); - putc('\t', outfp); - emitletter(tp->type); - fprintf(outfp, - "\t#%c%llX\n", - sizettype->letter, (long long) tp->n.elem); - return; - case UNION: - case STRUCT: - emitletter(tp); - tag = tp->tag->name; - fprintf(outfp, - "\t\"%s\t#%c%lX\t#%c%X\n", - (tag) ? tag : "", - sizettype->letter, - tp->size, - sizettype->letter, - tp->align); - n = tp->n.elem; - for (sp = tp->p.fields; n-- > 0; ++sp) - emit(ODECL, *sp); - break; - case PTR: - case FTN: - case ENUM: - return; - default: - abort(); - } -} - -static void -emitstring(Symbol *sym, Type *tp) -{ - char *bp, *s, *lim; - int n; - - bp = sym->u.s; - lim = &sym->u.s[tp->n.elem]; - while (bp < lim) { - s = bp; - while (bp < lim && isprint(*bp)) - ++bp; - if ((n = bp - s) > 1) - fprintf(outfp, "\t#\"%.*s\n", n, s); - else - bp = s; - if (bp == lim) - break; - do { - fprintf(outfp, - "\t#%c%02X\n", - chartype->letter, (*bp++) & 0xFF); - } while (bp < lim && !isprint(*bp)); - } -} - -static void -emitdesig(Node *np, Type *tp) -{ - Symbol *sym; - size_t n; /* TODO: This should be SIZET */ - Node *aux; - Type *p; - - if (!np) { - sym = NULL; - } else { - if (!np->sym) - goto emit_expression; - sym = np->sym; - if (sym->flags & SSTRING) { - emitstring(sym, tp); - return; - } - if ((sym->flags & SINITLST) == 0) - goto emit_expression; - } - - switch (tp->op) { - case PTR: - case INT: - case ENUM: - aux = (sym) ? *sym->u.init : convert(constnode(zero), tp, 0); - emitexp(OEXPR, aux); - break; - case UNION: - n = tp->n.elem-1; - aux = (sym) ? sym->u.init[0] : NULL; - emitdesig(aux, aux->type); - break; - case STRUCT: - case ARY: - for (n = 0; n < tp->n.elem; ++n) { - aux = (sym) ? sym->u.init[n] : NULL; - p = (tp->op == ARY) ? tp->type : tp->p.fields[n]->type; - emitdesig(aux, p); - } - break; - default: - abort(); - } - - if (sym) { - free(sym->u.init); - sym->u.init = NULL; - } - freetree(np); - return; - -emit_expression: - emitexp(OEXPR, np); -} - -static void -emitinit(int op, void *arg) -{ - Node *np = arg; - - fputs("\t(\n", outfp); - emitdesig(np, np->type); - fputs(")\n", outfp); -} - -static void -emitdcl(int op, void *arg) -{ - Symbol *sym = arg; - - if (sym->flags & SEMITTED) - return; - emitvar(sym); - putc('\t', outfp); - if (sym->type->op == FTN) { - emitletter(sym->type->type); - putc('\t', outfp); - } - emitletter(sym->type); - fprintf(outfp, "\t\"%s", (sym->name) ? sym->name : ""); - if (sym->flags & SFIELD) - fprintf(outfp, "\t#%c%llX", sizettype->letter, sym->u.i); - sym->flags |= SEMITTED; - if ((sym->flags & SHASINIT) == 0) - putc('\n', outfp); -} - -static void -emitcast(int op, void *arg) -{ - Node *np = arg, *lp = np->left; - - emitnode(lp); - if (np->type != voidtype) - fprintf(outfp, "\tg%c", np->type->letter); -} - -static void -emitbin(int op, void *arg) -{ - Node *np = arg; - char *s; - - emitnode(np->left); - emitnode(np->right); - if ((s = optxt[op]) != NULL) { /* do not print in OCOLON case */ - fprintf(outfp, "\t%s", s); - emitletter(np->type); - } -} - -static void -emitbuilt(int op, void *arg) -{ - Node *np = arg; - - emitnode(np->left); - emitnode(np->right); - fprintf(outfp, "\t\"%s\tm", np->sym->name); - emitletter(np->type); -} - - -static void -emitexp(int op, void *arg) -{ - Node *np = arg; - - emitnode(np); - putc('\n', outfp); - freetree(np); -} - -static void -emitfun(int op, void *arg) -{ - Symbol *sym = arg, **sp; - - emitdcl(op, arg); - fputs("{\n", outfp); - - for (sp = sym->u.pars; sp && *sp; ++sp) - emit(ODECL, *sp); - fputs("\\\n", outfp); -} - -static void -emittext(int op, void *arg) -{ - fputs(optxt[op], outfp); -} - -static void -emitsymid(int op, void *arg) -{ - Symbol *sym = arg; - fprintf(outfp, optxt[op], sym->id); -} - -Node * -node(int op, Type *tp, Node *lp, Node *rp) -{ - Node *np; - - np = xmalloc(sizeof(*np)); - np->op = op; - np->type = tp; - np->sym = NULL; - np->flags = 0; - np->left = lp; - np->right = rp; - - if (lp) - np->flags |= lp->flags & NEFFECT; - if (rp) - np->flags |= rp->flags & NEFFECT; - return np; -} - -Node * -varnode(Symbol *sym) -{ - Node *np; - Type *tp = sym->type; - - np = node(OSYM, sym->type, NULL, NULL); - np->type = sym->type; - np->flags = (tp->op != FTN && tp->op != ARY) ? NLVAL : 0; - np->sym = sym; - return np; -} - -Node * -constnode(Symbol *sym) -{ - Node *np; - - np = node(OSYM, sym->type, NULL, NULL); - np->type = sym->type; - np->flags = NCONST; - np->sym = sym; - return np; -} - -Node * -sizeofnode(Type *tp) -{ - Symbol *sym; - - sym = newsym(NS_IDEN, NULL); - sym->type = sizettype; - sym->u.i = tp->size; - return constnode(sym); -} diff --git a/cc1/cpp.c b/cc1/cpp.c @@ -1,839 +0,0 @@ -static char sccsid[] = "@(#) ./cc1/cpp.c"; -#include <ctype.h> -#include <limits.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> - -#include <cstd.h> -#include "../inc/scc.h" -#include "cc1.h" - -static char *argp, *macroname; -static unsigned arglen; -static unsigned ncmdlines; -static Symbol *symline, *symfile; -static unsigned char ifstatus[NR_COND]; -static int cppoff; -static struct items dirinclude; - -unsigned cppctx; -int disexpand; - -void -defdefine(char *macro, char *val, char *source) -{ - char *def, *fmt = "#define %s %s\n"; - Symbol dummy = {.flags = SDECLARED}; - - if (!val) - val = ""; - def = xmalloc(strlen(fmt) + strlen(macro) + strlen(val)); - - sprintf(def, fmt, macro, val); - lineno = ++ncmdlines; - addinput(source, &dummy, def); - cpp(); - delinput(); -} - -void -undefmacro(char *s) -{ - killsym(lookup(NS_CPP, s, NOALLOC)); -} - -void -icpp(void) -{ - static char sdate[14], stime[11]; - struct tm *tm; - time_t t; - static char **bp, *list[] = { - "__STDC__", - "__STDC_HOSTED__", - "__SCC__", - NULL - }; - static struct keyword keys[] = { - {"define", DEFINE, DEFINE}, - {"include", INCLUDE, INCLUDE}, - {"line", LINE, LINE}, - {"ifdef", IFDEF, IFDEF}, - {"if", IF, IF}, - {"elif", ELIF, ELIF}, - {"else", ELSE, ELSE}, - {"ifndef", IFNDEF, IFNDEF}, - {"endif", ENDIF, ENDIF}, - {"undef", UNDEF, UNDEF}, - {"pragma", PRAGMA, PRAGMA}, - {"error", ERROR, ERROR}, - {NULL, 0, 0} - }; - - keywords(keys, NS_CPPCLAUSES); - - t = time(NULL); - tm = localtime(&t); - strftime(sdate, sizeof(sdate), "\"%b %d %Y\"", tm); - strftime(stime, sizeof(stime), "\"%H:%M:%S\"", tm); - defdefine("__DATE__", sdate, "built-in"); - defdefine("__TIME__", stime, "built-in"); - defdefine("__STDC_VERSION__", STDC_VERSION, "built-in"); - defdefine("__LINE__", NULL, "built-in"); - defdefine("__FILE__", NULL, "built-in"); - - symline = lookup(NS_CPP, "__LINE__", ALLOC); - symfile = lookup(NS_CPP, "__FILE__", ALLOC); - - for (bp = list; *bp; ++bp) - defdefine(*bp, "1", "built-in"); - - ncmdlines = 0; -} - -static void -nextcpp(void) -{ - next(); - if (yytoken == EOFTOK) - error("unterminated argument list invoking macro \"%s\"", - macroname); - if (yylen + 1 > arglen) - error("argument overflow invoking macro \"%s\"", - macroname); - if (yytoken == IDEN) - yylval.sym->flags |= SUSED; - memcpy(argp, yytext, yylen); - argp += yylen; - *argp++ = ' '; - arglen -= yylen + 1; -} - -static void -paren(void) -{ - for (;;) { - nextcpp(); - switch (yytoken) { - case ')': - return; - case '(': - paren(); - break; - } - } -} - -static void -parameter(void) -{ - for (;;) { - nextcpp(); - switch (yytoken) { - case ')': - case ',': - argp -= 3; /* remove " , " or " ) "*/ - *argp++ = '\0'; - return; - case '(': - paren(); - break; - } - } -} - -static int -parsepars(char *buffer, char **listp, int nargs) -{ - int n; - - if (nargs == -1) - return -1; - if (ahead() != '(' && nargs > 0) - return 0; - - disexpand = 1; - next(); - n = 0; - argp = buffer; - arglen = INPUTSIZ; - if (ahead() == ')') { - next(); - } else { - do { - *listp++ = argp; - parameter(); - } while (++n < NR_MACROARG && yytoken == ','); - } - if (yytoken != ')') - error("incorrect macro function-alike invocation"); - disexpand = 0; - - if (n == NR_MACROARG) - error("too many parameters in macro \"%s\"", macroname); - if (n != nargs) { - error("macro \"%s\" received %d arguments, but it takes %d", - macroname, n, nargs); - } - - return 1; -} - -static size_t -copymacro(char *buffer, char *s, size_t bufsiz, char *arglist[]) -{ - int delim, prevc, c; - char *p, *arg, *bp = buffer; - size_t size; - - for (prevc = '\0'; c = *s; prevc = c, ++s) { - switch (c) { - case '$': - while (bp[-1] == ' ') - --bp, ++bufsiz; - while (s[1] == ' ') - ++s; - case '#': - break; - case '\'': - delim = '\''; - goto search_delim; - case '\"': - delim = '"'; - search_delim: - for (p = s; *++s != delim; ) - ; - size = s - p + 1; - if (size > bufsiz) - goto expansion_too_long; - memcpy(bp, p, size); - bufsiz -= size; - bp += size; - break; - case '@': - if (prevc == '#') - bufsiz -= 2; - arg = arglist[atoi(++s)]; - size = strlen(arg); - if (size > bufsiz) - goto expansion_too_long; - if (prevc == '#') - *bp++ = '"'; - memcpy(bp, arg, size); - bp += size; - if (prevc == '#') - *bp++ = '"'; - bufsiz -= size; - s += 2; - break; - default: - if (bufsiz-- == 0) - goto expansion_too_long; - *bp++ = c; - break; - } - } - *bp = '\0'; - - return bp - buffer; - -expansion_too_long: - error("macro expansion of \"%s\" too long", macroname); -} - -int -expand(char *begin, Symbol *sym) -{ - size_t elen; - int n, i; - char *s = sym->u.s; - char *arglist[NR_MACROARG], arguments[INPUTSIZ], buffer[INPUTSIZ]; - - macroname = sym->name; - if (sym == symfile) { - elen = sprintf(buffer, "\"%s\" ", filenam); - goto substitute; - } - if (sym == symline) { - elen = sprintf(buffer, "%d ", lineno); - goto substitute; - } - if (!s) - return 1; - - n = atoi(s); - if (!parsepars(arguments, arglist, atoi(s))) - return 0; - for (i = 0; i < n; ++i) - DBG("MACRO par%d:%s", i, arglist[i]); - - elen = copymacro(buffer, s+3, INPUTSIZ-1, arglist); - -substitute: - DBG("MACRO '%s' expanded to :'%s'", macroname, buffer); - buffer[elen] = '\0'; - addinput(filenam, sym, xstrdup(buffer)); - - return 1; -} - -static int -getpars(Symbol *args[NR_MACROARG]) -{ - int n, c; - Symbol *sym; - - c = *input->p; - next(); - if (c != '(') - return -1; - next(); /* skip the '(' */ - if (accept(')')) - return 0; - - n = 0; - do { - if (n == NR_MACROARG) { - cpperror("too many parameters in macro"); - return NR_MACROARG; - } - if (accept(ELLIPSIS)) { - args[n++] = NULL; - break; - } - if (yytoken != IDEN) { - cpperror("macro arguments must be identifiers"); - return NR_MACROARG; - } - sym = install(NS_IDEN, yylval.sym); - sym->flags |= SUSED; - args[n++] = sym; - next(); - } while (accept(',')); - expect(')'); - - return n; -} - -static int -getdefs(Symbol *args[NR_MACROARG], int nargs, char *bp, size_t bufsiz) -{ - Symbol **argp; - size_t len; - int prevc = 0, ispar; - - if (yytoken == '$') { - cpperror("'##' cannot appear at either ends of a macro expansion"); - return 0; - } - - for (;;) { - ispar = 0; - if (yytoken == IDEN && nargs >= 0) { - for (argp = args; argp < &args[nargs]; ++argp) { - if (*argp == yylval.sym) - break; - } - if (argp != &args[nargs]) { - sprintf(yytext, "@%02d@", (int) (argp - args)); - ispar = 1; - } - } - if (prevc == '#' && !ispar) { - cpperror("'#' is not followed by a macro parameter"); - return 0; - } - if (yytoken == '\n') - break; - - if ((len = strlen(yytext)) >= bufsiz) { - cpperror("macro too long"); - return 0; - } - if (yytoken == '$') { - *bp++ = '$'; - --bufsiz; - } else { - memcpy(bp, yytext, len); - bp += len; - bufsiz -= len; - } - if ((prevc = yytoken) != '#') { - *bp++ = ' '; - --bufsiz; - } - next(); - } - *bp = '\0'; - return 1; -} - -static void -define(void) -{ - Symbol *sym,*args[NR_MACROARG]; - char buff[LINESIZ+1]; - int n; - - if (cppoff) - return; - - namespace = NS_CPP; - next(); - - if (yytoken != IDEN) { - cpperror("macro names must be identifiers"); - return; - } - sym = yylval.sym; - if (sym->flags & SDECLARED) { - warn("'%s' redefined", yytext); - free(sym->u.s); - } else { - sym = install(NS_CPP, sym); - sym->flags |= SDECLARED|SSTRING; - } - - namespace = NS_IDEN; /* Avoid polution in NS_CPP */ - if ((n = getpars(args)) == NR_MACROARG) - goto delete; - if (n > 0 && !args[n-1]) /* it is a variadic function */ - --n; - sprintf(buff, "%02d#", n); - if (!getdefs(args, n, buff+3, LINESIZ-3)) - goto delete; - sym->u.s = xstrdup(buff); - DBG("MACRO '%s' defined as '%s'", sym->name, buff); - return; - -delete: - killsym(sym); -} - -void -incdir(char *dir) -{ - if (!dir || *dir == '\0') - die("cc1: incorrect -I flag"); - newitem(&dirinclude, dir); -} - -static int -includefile(char *dir, char *file, size_t filelen) -{ - size_t dirlen; - char path[FILENAME_MAX]; - - if (!dir) { - dirlen = 0; - if (filelen > FILENAME_MAX-1) - return 0; - } else { - dirlen = strlen(dir); - if (dirlen + filelen > FILENAME_MAX-2) - return 0; - memcpy(path, dir, dirlen); - if (dir[dirlen-1] != '/') - path[dirlen++] = '/'; - } - memcpy(path+dirlen, file, filelen); - path[dirlen + filelen] = '\0'; - - addinput(path, NULL, NULL); - return 1; -} - -static char * -cwd(char *buf) -{ - char *p, *s = filenam; - size_t len; - - if ((p = strrchr(s, '/')) == NULL) - return NULL; - if ((len = p - s) >= FILENAME_MAX) - die("cc1: current work directory too long"); - memcpy(buf, s, len); - buf[len] = '\0'; - return buf; -} - -static void -include(void) -{ - char dir[FILENAME_MAX], file[FILENAME_MAX], *p, **bp; - size_t filelen; - int n; - - if (cppoff) - return; - - namespace = NS_IDEN; - next(); - - switch (*yytext) { - case '<': - if ((p = strchr(input->begin, '>')) == NULL || p[-1] == '<') - goto bad_include; - filelen = p - input->begin; - if (filelen >= FILENAME_MAX) - goto too_long; - memcpy(file, input->begin, filelen); - file[filelen] = '\0'; - - input->begin = input->p = p+1; - if (next() != '\n') - goto trailing_characters; - - break; - case '"': - if (yylen < 3) - goto bad_include; - filelen = yylen-2; - if (filelen >= FILENAME_MAX) - goto too_long; - memcpy(file, yytext+1, filelen); - file[filelen] = '\0'; - - if (next() != '\n') - goto trailing_characters; - - if (includefile(cwd(dir), file, filelen)) - goto its_done; - break; - default: - goto bad_include; - } - - n = dirinclude.n; - for (bp = dirinclude.s; n--; ++bp) { - if (includefile(*bp, file, filelen)) - goto its_done; - } - cpperror("included file '%s' not found", file); - -its_done: - return; - -trailing_characters: - cpperror("trailing characters after preprocessor directive"); - return; - -too_long: - cpperror("too long file name in #include"); - return; - -bad_include: - cpperror("#include expects \"FILENAME\" or <FILENAME>"); - return; -} - -static void -line(void) -{ - long n; - char *endp, *fname; - - if (cppoff) - return; - - disexpand = 0; - next(); - n = strtol(yytext, &endp, 10); - if (n <= 0 || n > USHRT_MAX || *endp != '\0') { - cpperror("first parameter of #line is not a positive integer"); - return; - } - - next(); - if (yytoken == '\n') { - fname = NULL; - } else { - if (*yytext != '\"' || yylen == 1) { - cpperror("second parameter of #line is not a valid filename"); - return; - } - fname = yylval.sym->u.s; - } - setloc(fname, n - 1); - if (yytoken != '\n') - next(); -} - -static void -pragma(void) -{ - if (cppoff) - return; - next(); - warn("ignoring pragma '%s'", yytext); - *input->p = '\0'; - next(); -} - -static void -usererr(void) -{ - if (cppoff) - return; - cpperror("#error %s", input->p); - *input->p = '\0'; - next(); -} - -static void -ifclause(int negate, int isifdef) -{ - Symbol *sym; - unsigned n; - int status; - Node *expr; - - if (cppctx == NR_COND-1) - error("too many nesting levels of conditional inclusion"); - - n = cppctx++; - namespace = NS_CPP; - next(); - - if (isifdef) { - if (yytoken != IDEN) { - cpperror("no macro name given in #%s directive", - (negate) ? "ifndef" : "ifdef"); - return; - } - sym = yylval.sym; - next(); - status = (sym->flags & SDECLARED) != 0; - if (!status) - killsym(sym); - } else { - /* TODO: catch recovery here */ - if ((expr = constexpr()) == NULL) { - cpperror("parameter of #if is not an integer constant expression"); - return; - } - status = expr->sym->u.i != 0; - freetree(expr); - } - - if (negate) - status = !status; - if ((ifstatus[n] = status) == 0) - ++cppoff; -} - -static void -cppif(void) -{ - disexpand = 0; - ifclause(0, 0); -} - -static void -ifdef(void) -{ - ifclause(0, 1); -} - -static void -ifndef(void) -{ - ifclause(1, 1); -} - -static void -elseclause(void) -{ - int status; - - if (cppctx == 0) { - cpperror("#else without #ifdef/ifndef"); - return; - } - - status = ifstatus[cppctx-1]; - ifstatus[cppctx-1] = !status; - cppoff += (status) ? 1 : -1; -} - -static void -cppelse(void) -{ - elseclause(); - next(); -} - -static void -elif(void) -{ - elseclause(); - if (ifstatus[cppctx-1]) { - --cppctx; - cppif(); - } -} - -static void -endif(void) -{ - if (cppctx == 0) - error("#endif without #if"); - if (!ifstatus[--cppctx]) - --cppoff; - next(); -} - -static void -undef(void) -{ - if (cppoff) - return; - - namespace = NS_CPP; - next(); - if (yytoken != IDEN) { - error("no macro name given in #undef directive"); - return; - } - killsym(yylval.sym); - next(); -} - -int -cpp(void) -{ - static struct { - unsigned char token; - void (*fun)(void); - } *bp, clauses [] = { - {DEFINE, define}, - {INCLUDE, include}, - {LINE, line}, - {IFDEF, ifdef}, - {IF, cppif}, - {ELIF, elif}, - {IFNDEF, ifndef}, - {ELSE, cppelse}, - {ENDIF, endif}, - {UNDEF, undef}, - {PRAGMA, pragma}, - {ERROR, usererr}, - {0, NULL} - }; - int ns; - char *p; - - for (p = input->p; isspace(*p); ++p) - ; - - if (*p != '#') - return cppoff; - input->p = p+1; - - disexpand = 1; - lexmode = CPPMODE; - ns = namespace; - namespace = NS_CPPCLAUSES; - next(); - namespace = NS_IDEN; - - for (bp = clauses; bp->token && bp->token != yytoken; ++bp) - ; - if (!bp->token) { - errorp("incorrect preprocessor directive '%s'", yytext); - goto error; - } - - DBG("CPP %s", yytext); - - pushctx(); /* create a new context to avoid polish */ - (*bp->fun)(); /* the current context, and to get all */ - popctx(); /* the symbols freed at the end */ - - /* - * #include changes the content of input->line, so the correctness - * of the line must be checked in the own include(), and we have - * to skip this tests. For the same reason include() is the only - * function which does not prepare the next token - */ - if (yytoken != '\n' && !cppoff && bp->token != INCLUDE) - errorp("trailing characters after preprocessor directive"); - -error: - disexpand = 0; - lexmode = CCMODE; - namespace = ns; - - return 1; -} - -void -ppragmaln(void) -{ - static char file[FILENAME_MAX]; - static unsigned nline; - char *s; - - putchar('\n'); - if (strcmp(file, filenam)) { - strcpy(file, filenam); - s = "#line %u \"%s\"\n"; - } else if (nline+1 != lineno) { - s = "#line %u\n"; - } else { - s = ""; - } - nline = lineno; - printf(s, nline, file); -} - -void -outcpp(void) -{ - int c; - char *s, *t; - - for (next(); yytoken != EOFTOK; next()) { - if (onlyheader) - continue; - if (yytoken != STRING) { - printf("%s ", yytext); - continue; - } - for (s = yytext; c = *s; ++s) { - switch (c) { - case '\n': - t = "\\n"; - goto print_str; - case '\v': - t = "\\v"; - goto print_str; - case '\b': - t = "\\b"; - goto print_str; - case '\t': - t = "\\t"; - goto print_str; - case '\a': - t = "\\a"; - print_str: - fputs(t, stdout); - break; - case '\\': - putchar('\\'); - default: - if (!isprint(c)) - printf("\\x%x", c); - else - putchar(c); - break; - } - } - putchar(' '); - } - putchar('\n'); -} - diff --git a/cc1/decl.c b/cc1/decl.c @@ -1,967 +0,0 @@ -static char sccsid[] = "@(#) ./cc1/decl.c"; -#include <stdarg.h> -#include <stdlib.h> -#include <string.h> - -#include <cstd.h> -#include "../inc/scc.h" -#include "cc1.h" - -#define NOSCLASS 0 - -#define NOREP 0 -#define REP 1 -#define QUIET 1 -#define NOQUIET 0 - -#define NR_DCL_TYP (NR_DECLARATORS+NR_FUNPARAM) -#define NR_DCL_SYM (NR_DECLARATORS+NR_FUNPARAM+1) - -struct declarators { - unsigned nr; - unsigned ns; - struct decl *dcl; - unsigned nr_types; - Type **tpars; - Symbol **pars; - struct declarator { - unsigned char op; - TINT nelem; - Symbol *sym; - Type **tpars; - Symbol **pars; - } d [NR_DECLARATORS]; -}; - -struct decl { - unsigned ns; - int sclass; - int qualifier; - Symbol *sym; - Type *type; - Type *parent; - Symbol **pars; - Symbol *bufpars[NR_DCL_SYM]; - Type *buftpars[NR_DCL_TYP]; -}; - - -static void -endfundcl(Type *tp, Symbol **pars) -{ - if (tp->prop&TK_R && *pars) - warn("parameter names (without types) in function declaration"); - /* - * avoid non used warnings in prototypes - */ - while (*pars) - (*pars++)->flags |= SUSED; - popctx(); -} - -static void -push(struct declarators *dp, int op, ...) -{ - va_list va; - unsigned n; - struct declarator *p; - - va_start(va, op); - if ((n = dp->nr++) == NR_DECLARATORS) - error("too many declarators"); - - p = &dp->d[n]; - p->op = op; - p->tpars = NULL; - - switch (op) { - case ARY: - p->nelem = va_arg(va, TINT); - break; - case KRFTN: - case FTN: - p->nelem = va_arg(va, unsigned); - p->tpars = va_arg(va, Type **); - p->pars = va_arg(va, Symbol **); - break; - case IDEN: - p->sym = va_arg(va, Symbol *); - break; - } - va_end(va); -} - -static int -pop(struct declarators *dp, struct decl *dcl) -{ - struct declarator *p; - - if (dp->nr == 0) - return 0; - - p = &dp->d[--dp->nr]; - if (p->op == IDEN) { - dcl->sym = p->sym; - return 1; - } - - if (dcl->type->op == FTN) - endfundcl(dcl->type, dcl->pars); - dcl->pars = p->pars; - - dcl->type = mktype(dcl->type, p->op, p->nelem, p->tpars); - return 1; -} - -static void -arydcl(struct declarators *dp) -{ - Node *np = NULL; - TINT n = 0; - - expect('['); - if (yytoken != ']') { - if ((np = constexpr()) == NULL) { - errorp("invalid storage size"); - } else { - if ((n = np->sym->u.i) <= 0) { - errorp("array size is not a positive number"); - n = 1; - } - freetree(np); - } - } - expect(']'); - - push(dp, ARY, n); -} - -static int -empty(Symbol *sym, Type *tp, int param) -{ - if (!sym->name) { - sym->type = tp; - switch (tp->op) { - default: - /* warn if it is not a parameter */ - if (!param) - warn("empty declaration"); - case STRUCT: - case UNION: - case ENUM: - return 1; - } - } - return 0; -} - -static void -bad_storage(Type *tp, char *name) -{ - if (tp->op != FTN) - errorp("incorrect storage class for file-scope declaration"); - else - errorp("invalid storage class for function '%s'", name); -} - -static Symbol * -redcl(Symbol *sym, Type *tp, int sclass) -{ - int flags; - char *name = sym->name; - - if (!eqtype(sym->type, tp, 1)) { - errorp("conflicting types for '%s'", name); - return sym; - } - - if (sym->token == TYPEIDEN && sclass != TYPEDEF || - sym->token != TYPEIDEN && sclass == TYPEDEF) { - goto redeclaration; - } - if (curctx != GLOBALCTX && tp->op != FTN) { - /* is it the redeclaration of a local variable? */ - if ((sym->flags & SEXTERN) && sclass == EXTERN) - return sym; - goto redeclaration; - } - - flags = sym->flags; - switch (sclass) { - case REGISTER: - case AUTO: - bad_storage(tp, name); - break; - case NOSCLASS: - if ((flags & SPRIVATE) == 0) { - if (flags & SEXTERN) - flags &= ~(SEXTERN|SEMITTED); - flags |= SGLOBAL; - break; - } - errorp("non-static declaration of '%s' follows static declaration", - name); - break; - case TYPEDEF: - /* Only C11 allows multiple definitions of a typedef. */ - goto redeclaration; - case EXTERN: - break; - case STATIC: - if ((flags & (SGLOBAL|SEXTERN)) == 0) { - flags |= SPRIVATE; - break; - } - errorp("static declaration of '%s' follows non-static declaration", - name); - break; - } - sym->flags = flags; - - return sym; - -redeclaration: - errorp("redeclaration of '%s'", name); - return sym; -} - -static Symbol * -identifier(struct decl *dcl) -{ - Symbol *sym = dcl->sym; - Type *tp = dcl->type; - int sclass = dcl->sclass; - char *name = sym->name; - - if (empty(sym, tp, 0)) - return sym; - - /* TODO: Add warning about ANSI limits */ - if (!(tp->prop & TDEFINED) && - sclass != EXTERN && sclass != TYPEDEF && - !(tp->op == ARY && yytoken == '=')) { - errorp("declared variable '%s' of incomplete type", name); - } - - if (tp->op == FTN) { - if (sclass == NOSCLASS) - sclass = EXTERN; - if (!strcmp(name, "main") && tp->type != inttype) { - errorp("main shall be defined with a return type of int"); - errorp("please contact __20h__ on irc.freenode.net (#bitreich-en) via IRC"); - } - } - - if (sym->flags & SDECLARED) { - sym = redcl(dcl->sym, tp, sclass); - } else { - int flags = sym->flags | SDECLARED; - - sym->type = tp; - - switch (sclass) { - case REGISTER: - case AUTO: - if (curctx != GLOBALCTX && tp->op != FTN) { - flags |= (sclass == REGISTER) ? SREGISTER : SAUTO; - break; - } - bad_storage(tp, name); - case NOSCLASS: - if (tp->op == FTN) - flags |= SEXTERN; - else - flags |= (curctx == GLOBALCTX) ? SGLOBAL : SAUTO; - break; - case EXTERN: - flags |= SEXTERN; - break; - case STATIC: - flags |= (curctx == GLOBALCTX) ? SPRIVATE : SLOCAL; - break; - case TYPEDEF: - flags |= STYPEDEF; - sym->u.token = sym->token = TYPEIDEN; - break; - } - sym->flags = flags; - } - - if (accept('=')) - initializer(sym, sym->type); - if (!(sym->flags & (SGLOBAL|SEXTERN)) && tp->op != FTN) - sym->flags |= SDEFINED; - if (sym->token == IDEN && tp->op != FTN) - emit(ODECL, sym); - return sym; -} - -static Symbol * -parameter(struct decl *dcl) -{ - Symbol *sym = dcl->sym; - Type *funtp = dcl->parent, *tp = dcl->type; - char *name = sym->name; - int flags; - - flags = 0; - switch (dcl->sclass) { - case STATIC: - case EXTERN: - case AUTO: - errorp("bad storage class in function parameter"); - break; - case REGISTER: - flags |= SREGISTER; - break; - case NOSCLASS: - flags |= SAUTO; - break; - } - - switch (tp->op) { - case VOID: - funtp->n.elem = 1; - if (dcl->sclass) - errorp("void as unique parameter may not be qualified"); - return NULL; - case ARY: - tp = mktype(tp->type, PTR, 0, NULL); - break; - case FTN: - errorp("incorrect function type for a function parameter"); - return NULL; - } - if (!empty(sym, tp, 1)) { - int isdcl = sym->flags&SDECLARED, isk_r = funtp->prop & TK_R; - if (isdcl && !isk_r) { - errorp("redefinition of parameter '%s'", name); - return NULL; - } - if (!isdcl && isk_r) { - errorp("declaration for parameter '%s' but no such parameter", - sym->name); - return NULL; - } - sym->flags |= SDECLARED; - } - - sym->type = tp; - sym->flags &= ~(SAUTO|SREGISTER); - sym->flags |= flags; - return sym; -} - -static Symbol *dodcl(int rep, - Symbol *(*fun)(struct decl *), - unsigned ns, - Type *type); - -static int -krpars(struct declarators *dp) -{ - Symbol *sym; - int toomany = 0; - unsigned npars = 0; - - do { - sym = yylval.sym; - expect(IDEN); - sym->flags |= SAUTO; - if ((sym = install(NS_IDEN, sym)) == NULL) { - errorp("redefinition of parameter '%s'", - yylval.sym->name); - continue; - } - if (npars < NR_FUNPARAM) { - ++npars; - *dp->pars++ = sym; - continue; - } - if (!toomany) - toomany = 1; - } while (accept(',')); - - return toomany; -} - -static unsigned -krfun(struct declarators *dp) -{ - int toomany = 0; - - - if (yytoken != ')') - toomany = krpars(dp); - - if (dp->nr_types == NR_DCL_TYP) { - toomany = 1; - } else { - ++dp->nr_types; - *dp->tpars++ = ellipsistype; - } - - if (toomany) - errorp("too many parameters in function definition"); - return 1; -} - -static unsigned -ansifun(struct declarators *dp) -{ - Symbol *sym; - unsigned npars, ntype, toomany, distoomany, voidpar; - Type type, *tp; - - type.n.elem = 0; - type.prop = 0; - npars = ntype = toomany = distoomany = voidpar = 0; - - do { - if (accept(ELLIPSIS)) { - if (ntype < 1) - errorp("a named argument is requiered before '...'"); - if (yytoken != ')') - errorp("... must be the last parameter"); - sym = NULL; - tp = ellipsistype; - } else if ((sym = dodcl(NOREP, parameter, NS_IDEN, &type)) == NULL) { - if (type.n.elem == 1 && ntype > 1) - voidpar = 1; - sym = NULL; - tp = NULL; - } else { - tp = sym->type; - } - - if (sym) { - if (npars == NR_FUNPARAM) { - toomany = 1; - } else { - npars++; - *dp->pars++ = sym; - } - } - - if (tp) { - if (dp->nr_types == NR_DCL_TYP) { - toomany = 1; - } else { - ntype++; - dp->nr_types++; - *dp->tpars++ = tp; - } - } - - } while (accept(',')); - - if (toomany == 1) - errorp("too many parameters in function definition"); - if (voidpar && ntype > 1) - errorp("'void' must be the only parameter"); - return ntype; -} - -static int -funbody(Symbol *sym, Symbol *pars[]) -{ - Type *tp; - Symbol **bp, *p; - - if (!sym) - return 0; - tp = sym->type; - if (tp->op != FTN) - return 0; - - switch (yytoken) { - case '{': - case TYPE: - case TYPEIDEN: - if (curctx != PARAMCTX) - errorp("nested function declaration"); - if (sym && sym->ns == NS_IDEN) - break; - default: - emit(ODECL, sym); - endfundcl(tp, pars); - return 0; - } - - tp->prop |= TFUNDEF; - curfun = sym; - if (sym->type->prop & TK_R) { - while (yytoken != '{') { - dodcl(REP, parameter, NS_IDEN, sym->type); - expect(';'); - } - for (bp = pars; p = *bp; ++bp) { - if (p->type == NULL) { - warn("type of '%s' defaults to int", p->name); - p->type = inttype; - } - } - } - if (sym->flags & STYPEDEF) - errorp("function definition declared 'typedef'"); - if (sym->flags & SDEFINED) - errorp("redefinition of '%s'", sym->name); - if (sym->flags & SEXTERN) { - sym->flags &= ~SEXTERN; - sym->flags |= SGLOBAL; - } - sym->flags |= SDEFINED; - sym->flags &= ~SEMITTED; - sym->u.pars = pars; - emit(OFUN, sym); - compound(NULL, NULL, NULL); - emit(OEFUN, NULL); - popctx(); - flushtypes(); - curfun = NULL; - return 1; -} - -static void -fundcl(struct declarators *dp) -{ - Type **types = dp->tpars; - unsigned ntypes, typefun; - Symbol **pars = dp->pars; - unsigned (*fun)(struct declarators *); - - pushctx(); - expect('('); - if (yytoken == ')' || yytoken == IDEN) { - typefun = KRFTN; - fun = krfun; - } else { - typefun = FTN; - fun = ansifun; - } - ntypes = (*fun)(dp); - *dp->pars++= NULL; - expect(')'); - - push(dp, typefun, ntypes, types, pars); -} - -static void declarator(struct declarators *dp); - -static void -directdcl(struct declarators *dp) -{ - Symbol *p, *sym; - static int nested; - - if (accept('(')) { - if (nested == NR_SUBTYPE) - error("too many declarators nested by parentheses"); - ++nested; - declarator(dp); - --nested; - expect(')'); - } else { - if (yytoken == IDEN || yytoken == TYPEIDEN) { - sym = yylval.sym; - if (p = install(dp->ns, sym)) { - sym = p; - sym->flags &= ~SDECLARED; - } - next(); - } else { - sym = newsym(dp->ns, NULL); - } - push(dp, IDEN, sym); - } - - for (;;) { - switch (yytoken) { - case '(': fundcl(dp); break; - case '[': arydcl(dp); break; - default: return; - } - } -} - -static void -declarator(struct declarators *dp) -{ - unsigned n; - - for (n = 0; accept('*'); ++n) { - while (accept(TQUALIFIER)) - ; - } - - directdcl(dp); - - while (n--) - push(dp, PTR); -} - -static Type *structdcl(void), *enumdcl(void); - -static Type * -specifier(int *sclass, int *qualifier) -{ - Type *tp = NULL; - unsigned spec, qlf, sign, type, cls, size; - - spec = qlf = sign = type = cls = size = 0; - - for (;;) { - unsigned *p = NULL; - Type *(*dcl)(void) = NULL; - - switch (yytoken) { - case SCLASS: - p = &cls; - break; - case TQUALIFIER: - qlf |= yylval.token; - next(); - continue; - case TYPEIDEN: - if (type) - goto return_type; - tp = yylval.sym->type; - p = &type; - break; - case TYPE: - switch (yylval.token) { - case ENUM: - dcl = enumdcl; - p = &type; - break; - case STRUCT: - case UNION: - dcl = structdcl; - p = &type; - break; - case VA_LIST: - case VOID: - case BOOL: - case CHAR: - case INT: - case FLOAT: - case DOUBLE: - p = &type; - break; - case SIGNED: - case UNSIGNED: - p = &sign; - break; - case LONG: - if (size == LONG) { - yylval.token = LLONG; - size = 0; - } - case SHORT: - p = &size; - break; - } - break; - default: - goto return_type; - } - if (*p) - errorp("invalid type specification"); - *p = yylval.token; - if (dcl) { - if (size || sign) - errorp("invalid type specification"); - tp = (*dcl)(); - goto return_type; - } else { - next(); - } - spec = 1; - } - -return_type: - *sclass = cls; - *qualifier = qlf; - if (!tp) { - if (spec) { - tp = ctype(type, sign, size); - } else { - if (curctx != GLOBALCTX) - unexpected(); - warn("type defaults to 'int' in declaration"); - tp = inttype; - } - } - return tp; -} - -static Symbol * -newtag(void) -{ - Symbol *sym; - int ns, op, tag = yylval.token; - static unsigned tpns = NS_STRUCTS; - - ns = namespace; - namespace = NS_TAG; - next(); - namespace = ns; - - switch (yytoken) { - case IDEN: - case TYPEIDEN: - sym = yylval.sym; - if ((sym->flags & SDECLARED) == 0) - install(NS_TAG, yylval.sym); - next(); - break; - default: - sym = newsym(NS_TAG, NULL); - break; - } - if (!sym->type) { - Type *tp; - - if (tpns == NS_STRUCTS + NR_MAXSTRUCTS) - error("too many tags declared"); - tp = mktype(NULL, tag, 0, NULL); - tp->ns = tpns++; - sym->type = tp; - tp->tag = sym; - DBG("declared tag '%s' with ns = %d\n", - (sym->name) ? sym->name : "anonymous", tp->ns); - } - - if ((op = sym->type->op) != tag && op != INT) - error("'%s' defined as wrong kind of tag", sym->name); - return sym; -} - -static void fieldlist(Type *tp); - -static Type * -structdcl(void) -{ - Symbol *sym; - Type *tp; - static int nested; - int ns; - - sym = newtag(); - tp = sym->type; - - if (!accept('{')) - return tp; - - ns = namespace; - namespace = tp->ns; - - if (tp->prop & TDEFINED && sym->ctx == curctx) - error("redefinition of struct/union '%s'", sym->name); - - if (nested == NR_STRUCT_LEVEL) - error("too many levels of nested structure or union definitions"); - - ++nested; - while (yytoken != '}') { - fieldlist(tp); - } - --nested; - - deftype(tp); - namespace = ns; - expect('}'); - return tp; -} - -static Type * -enumdcl(void) -{ - Type *tp; - Symbol *sym, *tagsym; - int ns, val, toomany; - unsigned nctes; - - ns = namespace; - tagsym = newtag(); - tp = tagsym->type; - - if (!accept('{')) - goto restore_name; - if (tp->prop & TDEFINED) - errorp("redefinition of enumeration '%s'", tagsym->name); - deftype(tp); - namespace = NS_IDEN; - - /* TODO: check incorrect values in val */ - for (nctes = val = 0; yytoken != '}'; ++nctes, ++val) { - if (yytoken != IDEN) - unexpected(); - sym = yylval.sym; - next(); - if (nctes == NR_ENUM_CTES && !toomany) { - errorp("too many enum constants in a single enum"); - toomany = 1; - } - if (accept('=')) { - Node *np = constexpr(); - - if (np == NULL) - errorp("invalid enumeration value"); - else - val = np->sym->u.i; - freetree(np); - } - if ((sym = install(NS_IDEN, sym)) == NULL) { - errorp("'%s' redeclared as different kind of symbol", - yytext); - } else { - sym->u.i = val; - sym->flags |= SCONSTANT; - sym->type = inttype; - } - if (!accept(',')) - break; - } - expect('}'); - -restore_name: - namespace = ns; - return tp; -} - -static Symbol * -type(struct decl *dcl) -{ - Symbol *sym = dcl->sym; - - if (dcl->sclass) - error("class storage in type name"); - if (sym->name) - error("unexpected identifier in type name"); - sym->type = dcl->type; - - return sym; -} - -static Symbol * -field(struct decl *dcl) -{ - static char *anon = "<anonymous>"; - Symbol *sym = dcl->sym; - char *name = (sym->name) ? sym->name : anon; - Type *structp = dcl->parent, *tp = dcl->type; - TINT n = structp->n.elem; - int err = 0; - - if (accept(':')) { - Node *np; - TINT n; - - if ((np = constexpr()) == NULL) { - unexpected(); - n = 0; - } else { - n = np->sym->u.i; - freetree(np); - } - if (n == 0 && name != anon) - errorp("zero width for bit-field '%s'", name); - if (tp != booltype && tp != inttype && tp != uinttype) - errorp("bit-field '%s' has invalid type", name); - if (n < 0) - errorp("negative width in bit-field '%s'", name); - else if (n > tp->size*8) - errorp("width of '%s' exceeds its type", name); - } else if (empty(sym, tp, 0)) { - return sym; - } - - if (tp->op == FTN) { - errorp("invalid type '%s' in struct/union", name); - err = 1; - } - if (dcl->sclass) { - errorp("storage class in struct/union field '%s'", name); - err = 1; - } - if (!(tp->prop & TDEFINED)) { - error("field '%s' has incomplete type", name); - err = 1; - } - if (err) - return sym; - - if (sym->flags & SDECLARED) - error("duplicated member '%s'", name); - sym->flags |= SFIELD|SDECLARED; - sym->type = tp; - - if (n == NR_FIELDS) - error("too many fields in struct/union"); - DBG("New field '%s' in namespace %d\n", name, structp->ns); - structp->p.fields = xrealloc(structp->p.fields, ++n * sizeof(*sym)); - structp->p.fields[n-1] = sym; - structp->n.elem = n; - - return sym; -} - -static Symbol * -dodcl(int rep, Symbol *(*fun)(struct decl *), unsigned ns, Type *parent) -{ - Symbol *sym; - Type *base; - struct decl dcl; - struct declarators stack; - - dcl.ns = ns; - dcl.parent = parent; - base = specifier(&dcl.sclass, &dcl.qualifier); - - do { - dcl.type = base; - stack.nr_types = stack.nr = 0; - stack.tpars = dcl.buftpars; - stack.pars = dcl.bufpars; - stack.dcl = &dcl; - stack.ns = ns; - - declarator(&stack); - - while (pop(&stack, &dcl)) - ; - sym = (*fun)(&dcl); - if (funbody(sym, dcl.pars)) - return sym; - } while (rep && accept(',')); - - return sym; -} - -void -decl(void) -{ - Symbol *sym; - - if (accept(';')) - return; - sym = dodcl(REP, identifier, NS_IDEN, NULL); - if (sym->type->prop & TFUNDEF) - return; - expect(';'); -} - -static void -fieldlist(Type *tp) -{ - if (yytoken != ';') - dodcl(REP, field, tp->ns, tp); - expect(';'); -} - -Type * -typename(void) -{ - return dodcl(NOREP, type, NS_DUMMY, NULL)->type; -} diff --git a/cc1/deps.mk b/cc1/deps.mk @@ -1,45 +0,0 @@ -cpp.c: $(PROJECTDIR)/inc/$(STD)/cstd.h -decl.c: $(PROJECTDIR)/inc/$(STD)/cstd.h -expr.c: $(PROJECTDIR)/inc/$(STD)/cstd.h -init.c: $(PROJECTDIR)/inc/$(STD)/cstd.h -lex.c: $(PROJECTDIR)/inc/$(STD)/cstd.h -stmt.c: $(PROJECTDIR)/inc/$(STD)/cstd.h -symbol.c: $(PROJECTDIR)/inc/$(STD)/cstd.h -types.c: $(PROJECTDIR)/inc/$(STD)/cstd.h - -#deps -builtin.o: ../inc/scc.h -builtin.o: cc1.h -code.o: ../inc/scc.h -code.o: cc1.h -cpp.o: ../inc/scc.h -cpp.o: cc1.h -decl.o: ../inc/scc.h -decl.o: cc1.h -error.o: ../inc/scc.h -error.o: cc1.h -expr.o: ../inc/scc.h -expr.o: cc1.h -fold.o: ../inc/scc.h -fold.o: cc1.h -init.o: ../inc/scc.h -init.o: cc1.h -lex.o: ../inc/scc.h -lex.o: cc1.h -main.o: ../inc/arg.h -main.o: ../inc/scc.h -main.o: cc1.h -stmt.o: ../inc/scc.h -stmt.o: cc1.h -symbol.o: ../inc/scc.h -symbol.o: cc1.h -target/amd64-sysv/arch.o: target/amd64-sysv/../../../inc/scc.h -target/amd64-sysv/arch.o: target/amd64-sysv/../../cc1.h -target/arm64-sysv/arch.o: target/arm64-sysv/../../../inc/scc.h -target/arm64-sysv/arch.o: target/arm64-sysv/../../cc1.h -target/i386-sysv/arch.o: target/i386-sysv/../../../inc/scc.h -target/i386-sysv/arch.o: target/i386-sysv/../../cc1.h -target/z80-scc/arch.o: target/z80-scc/../../../inc/scc.h -target/z80-scc/arch.o: target/z80-scc/../../cc1.h -types.o: ../inc/scc.h -types.o: cc1.h diff --git a/cc1/error.c b/cc1/error.c @@ -1,85 +0,0 @@ -static char sccsid[] = "@(#) ./cc1/error.c"; -#include <stdarg.h> -#include <stdio.h> -#include <stdlib.h> - -#include "../inc/scc.h" -#include "cc1.h" - -#define MAXERRNUM 10 - -extern int failure; -static unsigned nerrors; - -static void -warn_error(int flag, char *fmt, va_list va) -{ - if (flag == 0) - return; - fprintf(stderr, "%s:%u: %s: ", - filenam, lineno, - (flag < 0) ? "error" : "warning"); - vfprintf(stderr, fmt, va); - putc('\n', stderr); - - if (flag < 0) { - if (!failure) - fclose(stdout); - failure = 1; - if (++nerrors == MAXERRNUM) { - fputs("too many errors\n", stderr); - exit(1); - } - } -} - -void -warn(char *fmt, ...) -{ - extern int warnings; - - va_list va; - va_start(va, fmt); - warn_error(warnings, fmt, va); - va_end(va); -} - -void -error(char *fmt, ...) -{ - va_list va; - - va_start(va, fmt); - warn_error(-1, fmt, va); - va_end(va); - exit(1); - discard(); -} - -void -errorp(char *fmt, ...) -{ - va_list va; - va_start(va, fmt); - warn_error(-1, fmt, va); - va_end(va); -} - -void -cpperror(char *fmt, ...) -{ - va_list va; - va_start(va, fmt); - warn_error(-1, fmt, va); - va_end(va); - - /* discard input until the end of the line */ - *input->p = '\0'; - next(); -} - -void -unexpected(void) -{ - error("unexpected '%s'", yytext); -} diff --git a/cc1/expr.c b/cc1/expr.c @@ -1,1185 +0,0 @@ -static char sccsid[] = "@(#) ./cc1/expr.c"; -#include <assert.h> -#include <stdlib.h> -#include <string.h> - -#include <cstd.h> -#include "../inc/scc.h" -#include "cc1.h" - -#define XCHG(lp, rp, np) (np = lp, lp = rp, rp = np) - -static Node *xexpr(void), *xassign(void); - -int -cmpnode(Node *np, TUINT val) -{ - Symbol *sym; - Type *tp; - TUINT mask, nodeval; - - if (!np || !(np->flags & NCONST) || !np->sym) - return 0; - sym = np->sym; - tp = sym->type; - - switch (tp->op) { - case PTR: - case INT: - mask = (val > 1) ? ones(np->type->size) : -1; - nodeval = (tp->prop & TSIGNED) ? sym->u.i : sym->u.u; - return (nodeval & mask) == (val & mask); - case FLOAT: - return sym->u.f == val; - } - return 0; -} - -static Node * -promote(Node *np) -{ - Type *tp; - Node *new; - struct limits *lim, *ilim; - - tp = np->type; - - switch (tp->op) { - case ENUM: - case INT: - if (tp->n.rank >= inttype->n.rank) - return np; - lim = getlimits(tp); - ilim = getlimits(inttype); - tp = (lim->max.i <= ilim->max.i) ? inttype : uinttype; - break; - case FLOAT: - /* TODO: Add support for C99 float math */ - tp = doubletype; - break; - default: - abort(); - } - if ((new = convert(np, tp, 1)) != NULL) - return new; - return np; -} - -static void -arithconv(Node **p1, Node **p2) -{ - int to = 0, s1, s2; - unsigned r1, r2; - Type *tp1, *tp2; - Node *np1, *np2; - struct limits *lp1, *lp2; - - np1 = promote(*p1); - np2 = promote(*p2); - - tp1 = np1->type; - tp2 = np2->type; - - if (tp1 == tp2) - goto set_p1_p2; - - s1 = (tp1->prop & TSIGNED) != 0; - r1 = tp1->n.rank; - lp1 = getlimits(tp1); - - s2 = (tp2->prop & TSIGNED) != 0; - r2 = tp2->n.rank; - lp2 = getlimits(tp2); - - if (s1 == s2 || tp1->op == FLOAT || tp2->op == FLOAT) { - to = r1 - r2; - } else if (!s1) { - if (r1 >= r2 || lp1->max.i >= lp2->max.i) - to = 1; - else - to = -1; - } else { - if (r2 >= r1 || lp2->max.i >= lp1->max.i) - to = -1; - else - to = 1; - } - - if (to > 0) - np2 = convert(np2, tp1, 1); - else if (to < 0) - np1 = convert(np1, tp2, 1); - -set_p1_p2: - *p1 = np1; - *p2 = np2; -} - -static int -null(Node *np) -{ - if (np->type != pvoidtype || np->op != OCAST) - return 0; - - np = np->left; - if (np->type != inttype) - return 0; - - return cmpnode(np, 0); -} - -static Node * -chkternary(Node *yes, Node *no) -{ - /* - * FIXME: - * We are ignoring type qualifiers here, - * but the standard has strong rules about this. - * take a look to 6.5.15 - */ - - if (!eqtype(yes->type, no->type, 1)) { - if ((yes->type->prop & TARITH) && (no->type->prop & TARITH)) { - arithconv(&yes, &no); - } else if (yes->type->op != PTR && no->type->op != PTR) { - goto wrong_type; - } else { - /* convert integer 0 to NULL */ - if ((yes->type->prop & TINTEGER) && cmpnode(yes, 0)) - yes = convert(yes, pvoidtype, 0); - if ((no->type->prop & TINTEGER) && cmpnode(no, 0)) - no = convert(no, pvoidtype, 0); - /* - * At this point the type of both should be - * a pointer to something, or we have don't - * compatible types - */ - if (yes->type->op != PTR || no->type->op != PTR) - goto wrong_type; - /* - * If we have a null pointer constant then - * convert to the another type - */ - if (null(yes)) - yes = convert(yes, no->type, 0); - if (null(no)) - no = convert(no, yes->type, 0); - - if (!eqtype(yes->type, no->type, 1)) - goto wrong_type; - } - } - return node(OCOLON, yes->type, yes, no); - -wrong_type: - errorp("type mismatch in conditional expression"); - freetree(yes); - freetree(no); - return constnode(zero); -} - -static void -chklvalue(Node *np) -{ - if (!(np->flags & NLVAL)) - errorp("lvalue required in operation"); - if (np->type == voidtype) - errorp("invalid use of void expression"); -} - -Node * -decay(Node *np) -{ - Node *new; - Type *tp = np->type; - - switch (tp->op) { - case ARY: - tp = tp->type; - if (np->op == OPTR) { - new = np->left; - free(np); - new->type = mktype(tp, PTR, 0, NULL); - return new; - } - case FTN: - new = node(OADDR, mktype(tp, PTR, 0, NULL), np, NULL); - if (np->sym && np->sym->flags & (SGLOBAL|SLOCAL|SPRIVATE)) - new->flags |= NCONST; - return new; - default: - return np; - } -} - -static Node * -integerop(int op, Node *lp, Node *rp) -{ - if (!(lp->type->prop & TINTEGER) || !(rp->type->prop & TINTEGER)) - error("operator requires integer operands"); - arithconv(&lp, &rp); - return node(op, lp->type, lp, rp); -} - -static Node * -integeruop(int op, Node *np) -{ - if (!(np->type->prop & TINTEGER)) - error("unary operator requires integer operand"); - np = promote(np); - return node(op, np->type, np, NULL); -} - -static Node * -numericaluop(int op, Node *np) -{ - if (!(np->type->prop & TARITH)) - error("unary operator requires numerical operand"); - np = promote(np); - return node(op, np->type, np, NULL); -} - -Node * -convert(Node *np, Type *newtp, int iscast) -{ - Type *oldtp = np->type; - - if (eqtype(newtp, oldtp, 0)) - return np; - - switch (oldtp->op) { - case ENUM: - case INT: - case FLOAT: - switch (newtp->op) { - case PTR: - if (oldtp->op == FLOAT || !cmpnode(np, 0) && !iscast) - return NULL; - case INT: - case FLOAT: - case ENUM: - break; - default: - return NULL; - } - break; - case PTR: - switch (newtp->op) { - case ENUM: - case INT: - case VOID: - if (!iscast) - return NULL; - break; - case PTR: - if (eqtype(newtp, oldtp, 1) || - iscast || - newtp == pvoidtype || oldtp == pvoidtype) { - np->type = newtp; - return np; - } - default: - return NULL; - } - break; - default: - return NULL; - } - return node(OCAST, newtp, np, NULL); -} - -static Node * -parithmetic(int op, Node *lp, Node *rp) -{ - Type *tp; - Node *size, *np; - - if (lp->type->op != PTR) - XCHG(lp, rp, np); - - tp = rp->type; - if (tp->op == PTR && !(tp->type->prop & TDEFINED)) - goto incomplete; - tp = lp->type; - if (!(tp->type->prop & TDEFINED)) - goto incomplete; - size = sizeofnode(tp->type); - - if (op == OSUB && BTYPE(rp) == PTR) { - if ((rp = convert(rp, lp->type, 0)) == NULL) - goto incorrect; - lp = node(OSUB, pdifftype, lp, rp); - return node(ODIV, inttype, lp, size); - } - if (!(rp->type->prop & TINTEGER)) - goto incorrect; - - rp = convert(promote(rp), sizettype, 0); - rp = node(OMUL, sizettype, rp, size); - rp = convert(rp, tp, 1); - - return node(op, tp, lp, rp); - -incomplete: - errorp("invalid use of undefined type"); - return lp; -incorrect: - errorp("incorrect arithmetic operands"); - return lp; - -} - -static Node * -arithmetic(int op, Node *lp, Node *rp) -{ - Type *ltp = lp->type, *rtp = rp->type; - - if ((ltp->prop & TARITH) && (rtp->prop & TARITH)) { - arithconv(&lp, &rp); - return node(op, lp->type, lp, rp); - } else if ((ltp->op == PTR || rtp->op == PTR)) { - switch (op) { - case OADD: - case OSUB: - case OA_ADD: - case OA_SUB: - case OINC: - case ODEC: - return parithmetic(op, lp, rp); - } - } - errorp("incorrect arithmetic operands"); -} - -static Node * -pcompare(int op, Node *lp, Node *rp) -{ - Node *np; - - if (lp->type->prop & TINTEGER) - XCHG(lp, rp, np); - else if (eqtype(lp->type, pvoidtype, 1)) - XCHG(lp, rp, np); - - if ((np = convert(rp, lp->type, 0)) != NULL) - rp = np; - else - errorp("incompatible types in comparison"); - return convert(node(op, pvoidtype, lp, rp), inttype, 1); -} - -static Node * -compare(int op, Node *lp, Node *rp) -{ - Type *ltp, *rtp; - - ltp = lp->type; - rtp = rp->type; - - if (ltp->op == PTR || rtp->op == PTR) { - return pcompare(op, rp, lp); - } else if ((ltp->prop & TARITH) && (rtp->prop & TARITH)) { - arithconv(&lp, &rp); - return convert(node(op, lp->type, lp, rp), inttype, 1);; - } else { - errorp("incompatible types in comparison"); - freetree(lp); - freetree(rp); - return constnode(zero); - } -} - -int -negop(int op) -{ - switch (op) { - case OEQ: return ONE; - case ONE: return OEQ; - case OLT: return OGE; - case OGE: return OLT; - case OLE: return OGT; - case OGT: return OLE; - default: abort(); - } - return op; -} - -static Node * -exp2cond(Node *np, int neg) -{ - if (np->type->prop & TAGGREG) { - errorp("used struct/union type value where scalar is required"); - return constnode(zero); - } - switch (np->op) { - case ONEG: - case OOR: - case OAND: - return (neg) ? node(ONEG, inttype, np, NULL) : np; - case OEQ: - case ONE: - case OLT: - case OGE: - case OLE: - case OGT: - if (neg) - np->op = negop(np->op); - return np; - default: - return compare((neg) ? OEQ : ONE, np, constnode(zero)); - } -} - -static Node * -logic(int op, Node *lp, Node *rp) -{ - lp = exp2cond(lp, 0); - rp = exp2cond(rp, 0); - return node(op, inttype, lp, rp); -} - -static Node * -field(Node *np) -{ - Symbol *sym; - - namespace = np->type->ns; - next(); - namespace = NS_IDEN; - - sym = yylval.sym; - if (yytoken != IDEN) - unexpected(); - next(); - - if (!(np->type->prop & TAGGREG)) { - errorp("request for member '%s' in something not a structure or union", - yylval.sym->name); - goto free_np; - } - if ((sym->flags & SDECLARED) == 0) { - errorp("incorrect field in struct/union"); - goto free_np; - } - np = node(OFIELD, sym->type, np, varnode(sym)); - np->flags |= NLVAL; - return np; - -free_np: - freetree(np); - return constnode(zero); -} - -static Node * -content(int op, Node *np) -{ - if (BTYPE(np) != PTR) { - errorp("invalid argument of memory indirection"); - } else { - if (np->op == OADDR) { - Node *new = np->left; - new->type = np->type->type; - free(np); - np = new; - } else { - np = node(op, np->type->type, np, NULL); - } - np->flags |= NLVAL; - } - return np; -} - -static Node * -array(Node *lp, Node *rp) -{ - Type *tp; - Node *np; - - if (!(lp->type->prop & TINTEGER) && !(rp->type->prop & TINTEGER)) - error("array subscript is not an integer"); - np = arithmetic(OADD, lp, rp); - tp = np->type; - if (tp->op != PTR) - errorp("subscripted value is neither array nor pointer"); - return content(OPTR, np); -} - -static Node * -assignop(int op, Node *lp, Node *rp) -{ - if ((rp = convert(rp, lp->type, 0)) == NULL) { - errorp("incompatible types when assigning"); - return lp; - } - - return node(op, lp->type, lp, rp); -} - -static Node * -incdec(Node *np, int op) -{ - Type *tp = np->type; - Node *inc; - - chklvalue(np); - np->flags |= NEFFECT; - - if (!(tp->prop & TDEFINED)) { - errorp("invalid use of undefined type"); - return np; - } else if (tp->op == PTR && !(tp->type->prop & TDEFINED)) { - errorp("%s of pointer to an incomplete type", - (op == OINC || op == OA_ADD) ? "increment" : "decrement"); - return np; - } else if (tp->op == PTR || (tp->prop & TARITH)) { - inc = constnode(one); - } else { - errorp("wrong type argument to increment or decrement"); - return np; - } - return arithmetic(op, np, inc); -} - -static Node * -address(int op, Node *np) -{ - Node *new; - - /* - * ansi c accepts & applied to a function name, and it generates - * a function pointer - */ - if (np->op == OSYM) { - if (np->type->op == FTN) - return decay(np); - if (np->type->op == ARY) - goto dont_check_lvalue; - } - chklvalue(np); - -dont_check_lvalue: - if (np->sym && (np->sym->flags & SREGISTER)) - errorp("address of register variable '%s' requested", yytext); - new = node(op, mktype(np->type, PTR, 0, NULL), np, NULL); - if (np->sym && np->sym->flags & (SGLOBAL|SLOCAL|SPRIVATE)) - new->flags |= NCONST; - return new; -} - -static Node * -negation(int op, Node *np) -{ - if (!(np->type->prop & TARITH) && np->type->op != PTR) { - errorp("invalid argument of unary '!'"); - return constnode(zero); - } - return exp2cond(np, 1); -} - -static Symbol * -notdefined(Symbol *sym) -{ - int isdef; - - if (namespace == NS_CPP && !strcmp(sym->name, "defined")) { - disexpand = 1; - next(); - expect('('); - sym = yylval.sym; - expect(IDEN); - expect(')'); - - isdef = (sym->flags & SDECLARED) != 0; - sym = newsym(NS_IDEN, NULL); - sym->type = inttype; - sym->flags |= SCONSTANT; - sym->u.i = isdef; - disexpand = 0; - return sym; - } - errorp("'%s' undeclared", yytext); - sym->type = inttype; - return install(sym->ns, yylval.sym); -} - -static Symbol * -adjstrings(Symbol *sym) -{ - char *s, *t; - size_t len, n; - Type *tp; - - tp = sym->type; - s = sym->u.s; - for (len = strlen(s);; len += n) { - next(); - if (yytoken != STRING) - break; - t = yylval.sym->u.s; - n = strlen(t); - s = xrealloc(s, len + n + 1); - memcpy(s+len, t, n); - s[len + n] = '\0'; - killsym(yylval.sym); - } - ++len; - if (tp->n.elem != len) { - sym->type = mktype(chartype, ARY, len, NULL); - sym->u.s = s; - } - return sym; -} - -/************************************************************* - * grammar functions * - *************************************************************/ -static Node * -primary(void) -{ - Node *np; - Symbol *sym; - Node *(*fun)(Symbol *); - - sym = yylval.sym; - switch (yytoken) { - case STRING: - np = constnode(adjstrings(sym)); - sym->flags |= SHASINIT; - emit(ODECL, sym); - emit(OINIT, np); - return varnode(sym); - case BUILTIN: - fun = sym->u.fun; - next(); - expect('('); - np = (*fun)(sym); - expect(')'); - - /* do not call to next */ - return np; - case CONSTANT: - np = constnode(sym); - break; - case IDEN: - assert((sym->flags & SCONSTANT) == 0); - if ((sym->flags & SDECLARED) == 0) { - if (namespace == NS_CPP) { - np = constnode(zero); - break; - } - sym = notdefined(sym); - } - sym->flags |= SUSED; - np = varnode(sym); - break; - default: - unexpected(); - } - next(); - - return np; -} - -static Node * -arguments(Node *np) -{ - int toomany, n, op; - Node *par = NULL, *arg; - Type *argtype, **targs, *tp = np->type, *rettype; - - if (tp->op == PTR && tp->type->op == FTN) { - np = content(OPTR, np); - tp = np->type; - } - if (tp->op != FTN) { - targs = (Type *[]) {ellipsistype}; - n = 1; - rettype = inttype; - errorp("function or function pointer expected"); - } else { - targs = tp->p.pars; - n = tp->n.elem; - rettype = tp->type; - } - - expect('('); - if (yytoken == ')') - goto no_pars; - toomany = 0; - - do { - arg = xassign(); - argtype = *targs; - if (argtype == ellipsistype) { - n = 0; - switch (arg->type->op) { - case INT: - arg = promote(arg); - break; - case FLOAT: - if (arg->type == floattype) - arg = convert(arg, doubletype, 1); - break; - } - par = node(OPAR, arg->type, par, arg); - continue; - } - if (--n < 0) { - if (!toomany) - errorp("too many arguments in function call"); - toomany = 1; - continue; - } - ++targs; - if ((arg = convert(arg, argtype, 0)) != NULL) { - par = node(OPAR, arg->type, par, arg); - continue; - } - errorp("incompatible type for argument %d in function call", - tp->n.elem - n + 1); - } while (accept(',')); - -no_pars: - expect(')'); - if (n > 0 && *targs != ellipsistype) - errorp("too few arguments in function call"); - - op = (tp->prop&TELLIPSIS) ? OCALLE : OCALL; - return node(op, rettype, np, par); -} - -static Node *unary(int); - -static Type * -typeof(Node *np) -{ - Type *tp; - - if (np == NULL) - unexpected(); - tp = np->type; - freetree(np); - return tp; -} - -static Type * -sizeexp(void) -{ - Type *tp; - - expect('('); - switch (yytoken) { - case TYPE: - case TYPEIDEN: - tp = typename(); - break; - default: - tp = typeof(unary(0)); - break; - } - expect(')'); - return tp; -} - -static Node * -postfix(Node *lp) -{ - Node *rp; - - for (;;) { - switch (yytoken) { - case '[': - case DEC: - case INC: - case INDIR: - case '.': - case '(': - lp = decay(lp); - switch (yytoken) { - case '[': - next(); - rp = xexpr(); - expect(']'); - lp = array(lp, rp); - break; - case DEC: - case INC: - lp = incdec(lp, (yytoken == INC) ? OINC : ODEC); - next(); - break; - case INDIR: - lp = content(OPTR, lp); - case '.': - lp = field(lp); - break; - case '(': - lp = arguments(lp); - lp->flags |= NEFFECT; - break; - } - break; - default: - return lp; - } - } -} - -static Node * -defined(void) -{ - Symbol *sym; - int paren; - - disexpand = 1; - next(); - paren = accept('('); - if (yytoken != IDEN && yytoken != TYPEIDEN) - cpperror("operator 'defined' requires an identifier"); - if (yytoken == TYPEIDEN || !(yylval.sym->flags & SDECLARED)) - sym = zero; - else - sym = one; - disexpand = 0; - next(); - if (paren) - expect(')'); - return constnode(sym); -} - -static Node *cast(int); - -static Node * -unary(int needdecay) -{ - Node *(*fun)(int, Node *), *np; - int op; - Type *tp; - - switch (yytoken) { - case '!': op = 0; fun = negation; break; - case '+': op = OADD; fun = numericaluop; break; - case '-': op = OSNEG; fun = numericaluop; break; - case '~': op = OCPL; fun = integeruop; break; - case '&': op = OADDR; fun = address; break; - case '*': op = OPTR; fun = content; break; - case SIZEOF: - next(); - tp = (yytoken == '(') ? sizeexp() : typeof(unary(0)); - if (!(tp->prop & TDEFINED)) - errorp("sizeof applied to an incomplete type"); - return sizeofnode(tp); - case INC: - case DEC: - op = (yytoken == INC) ? OA_ADD : OA_SUB; - next(); - np = incdec(unary(1), op); - goto chk_decay; - case IDEN: - case TYPEIDEN: - if (lexmode == CPPMODE && !strcmp(yylval.sym->name, "defined")) - return defined(); - default: - np = postfix(primary()); - goto chk_decay; - } - - next(); - np = (*fun)(op, cast(op != OADDR)); - -chk_decay: - if (needdecay) - np = decay(np); - return np; -} - -static Node * -cast(int needdecay) -{ - Node *lp, *rp; - Type *tp; - static int nested; - - if (!accept('(')) - return unary(needdecay); - - switch (yytoken) { - case TQUALIFIER: - case TYPE: - case TYPEIDEN: - tp = typename(); - expect(')'); - - if (yytoken == '{') - return initlist(tp); - - switch (tp->op) { - case ARY: - error("cast specifies an array type"); - default: - lp = cast(needdecay); - if ((rp = convert(lp, tp, 1)) == NULL) - error("bad type conversion requested"); - rp->flags &= ~NLVAL; - rp->flags |= lp->flags & NLVAL; - } - break; - default: - if (nested == NR_SUBEXPR) - error("too many expressions nested by parentheses"); - ++nested; - rp = xexpr(); - --nested; - expect(')'); - rp = postfix(rp); - break; - } - - return rp; -} - -static Node * -mul(void) -{ - Node *np, *(*fun)(int, Node *, Node *); - int op; - - np = cast(1); - for (;;) { - switch (yytoken) { - case '*': op = OMUL; fun = arithmetic; break; - case '/': op = ODIV; fun = arithmetic; break; - case '%': op = OMOD; fun = integerop; break; - default: return np; - } - next(); - np = (*fun)(op, np, cast(1)); - } -} - -static Node * -add(void) -{ - int op; - Node *np; - - np = mul(); - for (;;) { - switch (yytoken) { - case '+': op = OADD; break; - case '-': op = OSUB; break; - default: return np; - } - next(); - np = arithmetic(op, np, mul()); - } -} - -static Node * -shift(void) -{ - int op; - Node *np; - - np = add(); - for (;;) { - switch (yytoken) { - case SHL: op = OSHL; break; - case SHR: op = OSHR; break; - default: return np; - } - next(); - np = integerop(op, np, add()); - } -} - -static Node * -relational(void) -{ - int op; - Node *np; - - np = shift(); - for (;;) { - switch (yytoken) { - case '<': op = OLT; break; - case '>': op = OGT; break; - case GE: op = OGE; break; - case LE: op = OLE; break; - default: return np; - } - next(); - np = compare(op, np, shift()); - } -} - -static Node * -eq(void) -{ - int op; - Node *np; - - np = relational(); - for (;;) { - switch (yytoken) { - case EQ: op = OEQ; break; - case NE: op = ONE; break; - default: return np; - } - next(); - np = compare(op, np, relational()); - } -} - -static Node * -bit_and(void) -{ - Node *np; - - np = eq(); - while (accept('&')) - np = integerop(OBAND, np, eq()); - return np; -} - -static Node * -bit_xor(void) -{ - Node *np; - - np = bit_and(); - while (accept('^')) - np = integerop(OBXOR, np, bit_and()); - return np; -} - -static Node * -bit_or(void) -{ - Node *np; - - np = bit_xor(); - while (accept('|')) - np = integerop(OBOR, np, bit_xor()); - return np; -} - -static Node * -and(void) -{ - Node *np; - - np = bit_or(); - while (accept(AND)) - np = logic(OAND, np, bit_or()); - return np; -} - -static Node * -or(void) -{ - Node *np; - - np = and(); - while (accept(OR)) - np = logic(OOR, np, and()); - return np; -} - -static Node * -ternary(void) -{ - Node *cond; - - cond = or(); - while (accept('?')) { - Node *ifyes, *ifno, *np; - - cond = exp2cond(cond, 0); - ifyes = xexpr(); - expect(':'); - ifno = ternary(); - np = chkternary(ifyes, ifno); - cond = node(OASK, np->type, cond, np); - } - return cond; -} - -static Node * -xassign(void) -{ - Node *np, *(*fun)(int , Node *, Node *); - int op; - - np = ternary(); - for (;;) { - switch (yytoken) { - case '=': op = OASSIGN; fun = assignop; break; - case MUL_EQ: op = OA_MUL; fun = arithmetic; break; - case DIV_EQ: op = OA_DIV; fun = arithmetic; break; - case MOD_EQ: op = OA_MOD; fun = integerop; break; - case ADD_EQ: op = OA_ADD; fun = arithmetic; break; - case SUB_EQ: op = OA_SUB; fun = arithmetic; break; - case SHL_EQ: op = OA_SHL; fun = integerop; break; - case SHR_EQ: op = OA_SHR; fun = integerop; break; - case AND_EQ: op = OA_AND; fun = integerop; break; - case XOR_EQ: op = OA_XOR; fun = integerop; break; - case OR_EQ: op = OA_OR; fun = integerop; break; - default: return np; - } - chklvalue(np); - np->flags |= NEFFECT; - next(); - np = (fun)(op, np, assign()); - } -} - -static Node * -xexpr(void) -{ - Node *lp, *rp; - - lp = xassign(); - while (accept(',')) { - rp = xassign(); - lp = node(OCOMMA, rp->type, lp, rp); - } - return lp; -} - -Node * -assign(void) -{ - return simplify(xassign()); -} - -Node * -constexpr(void) -{ - Node *np; - - np = ternary(); - if (np && np->type->op == INT) { - np = simplify(convert(np, inttype, 0)); - if (np->flags & NCONST) - return np; - } - freetree(np); - return NULL; -} - -Node * -expr(void) -{ - return simplify(xexpr()); -} - -Node * -condexpr(int neg) -{ - Node *np; - - np = exp2cond(xexpr(), neg); - if (np->flags & NCONST) - warn("conditional expression is constant"); - return simplify(np); -} diff --git a/cc1/fold.c b/cc1/fold.c @@ -1,685 +0,0 @@ -static char sccsid[] = "@(#) ./cc1/fold.c"; -#include <assert.h> -#include <stdlib.h> - -#include "../inc/scc.h" -#include "cc1.h" - - -TUINT -ones(int nbytes) -{ - return (nbytes == 8) ? -1 : ~(-1ull << nbytes * 8); -} - -static int -addi(TINT l, TINT r, Type *tp) -{ - struct limits *lim = getlimits(tp); - TINT max = lim->max.i, min = -lim->min.i; - - if (l < 0 && r < 0 && l >= min - r || - l == 0 || - r == 0 || - l < 0 && r > 0 || - l > 0 && r < 0 || - l > 0 && r > 0 && l <= max - r) { - return 1; - } - warn("overflow in constant expression"); - return 0; -} - -static int -addf(TFLOAT l, TFLOAT r, Type *tp) -{ - struct limits *lim = getlimits(tp); - TFLOAT max = lim->max.f, min = lim->min.f; - - if (l < 0 && r < 0 && l >= min - r || - l == 0 || - r == 0 || - l < 0 && r > 0 || - l > 0 && r < 0 || - l > 0 && r > 0 && l <= max - r) { - return 1; - } - warn("overflow in constant expression"); - return 0; -} - -static int -subi(TINT l, TINT r, Type *tp) -{ - return addi(l, -r, tp); -} - -static int -subf(TFLOAT l, TFLOAT r, Type *tp) -{ - return addf(l, -r, tp); -} - -static int -muli(TINT l, TINT r, Type *tp) -{ - struct limits *lim = getlimits(tp); - TINT max = lim->max.i, min = -lim->min.i; - - if (l > -1 && l <= 1 || - r > -1 && r <= 1 || - l < 0 && r < 0 && -l <= max/-r || - l < 0 && r > 0 && l >= min/r || - l > 0 && r < 0 && r >= min/l || - l > 0 && r > 0 && l <= max/r) { - return 1; - } - warn("overflow in constant expression"); - return 0; -} - -static int -mulf(TFLOAT l, TFLOAT r, Type *tp) -{ - struct limits *lim = getlimits(tp); - TFLOAT max = lim->max.f, min = lim->min.f; - - if (l > -1 && l <= 1 || - r > -1 && r <= 1 || - l < 0 && r < 0 && -l <= max/-r || - l < 0 && r > 0 && l >= min/r || - l > 0 && r < 0 && r >= min/l || - l > 0 && r > 0 && l <= max/r) { - return 1; - } - warn("overflow in constant expression"); - return 0; -} - -static int -divi(TINT l, TINT r, Type *tp) -{ - struct limits *lim = getlimits(tp); - - if (r == 0 || l == -lim->min.i && r == -1) { - warn("overflow in constant expression"); - return 0; - } - return 1; -} - -static int -divf(TFLOAT l, TFLOAT r, Type *tp) -{ - struct limits *lim = getlimits(tp); - - if (l < 0) l = -l; - if (r < 0) r = -r; - - if (r == 0.0 || r < 1.0 && l > lim->max.f * r) { - warn("overflow in constant expression"); - return 0; - } - return 1; -} - -static int -lshi(TINT l, TINT r, Type *tp) -{ - if (r < 0 || r >= tp->size * 8) { - warn("shifting %d bits is undefined", r); - return 0; - } - return muli(l, 1 << r, tp); -} - -static int -rshi(TINT l, TINT r, Type *tp) -{ - if (r < 0 || r >= tp->size * 8) { - warn("shifting %d bits is undefined", r); - return 0; - } - return 1; -} - -static int -foldint(int op, Symbol *res, TINT l, TINT r) -{ - TINT i; - Type *tp = res->type; - int (*validate)(TINT, TINT, Type *tp); - - switch (op) { - case OADD: validate = addi; break; - case OSUB: validate = subi; break; - case OMUL: validate = muli; break; - case ODIV: validate = divi; break; - case OSHL: validate = lshi; break; - case OSHR: validate = rshi; break; - case OMOD: validate = divi; break; - default: validate = NULL; break; - } - - if (validate && !(*validate)(l, r, tp)) - return 0; - - switch (op) { - case OADD: i = l + r; break; - case OSUB: i = l - r; break; - case OMUL: i = l * r; break; - case ODIV: i = l / r; break; - case OMOD: i = l % r; break; - case OSHL: i = l << r; break; - case OSHR: i = l >> r; break; - case OBAND: i = l & r; break; - case OBXOR: i = l ^ r; break; - case OBOR: i = l | r; break; - case OAND: i = l && r; break; - case OOR: i = l || r; break; - case OLT: i = l < r; break; - case OGT: i = l > r; break; - case OGE: i = l >= r; break; - case OLE: i = l <= r; break; - case OEQ: i = l == r; break; - case ONE: i = l != r; break; - case ONEG: i = !l; break; - case OSNEG: i = -l; break; - case OCPL: i = ~l; break; - default: return 0; - } - res->u.i = i; - - DBG("FOLD i l=%lld %d r=%lld = %lld", l, op, r, i); - return 1; -} - -static int -folduint(int op, Symbol *res, TUINT l, TUINT r) -{ - TINT i; - TUINT u; - - switch (op) { - case OADD: u = l + r; break; - case OSUB: u = l - r; break; - case OMUL: u = l * r; break; - case ODIV: u = l / r; break; - case OMOD: u = l % r; break; - case OSHL: u = l << r; break; - case OSHR: u = l >> r; break; - case OBAND: u = l & r; break; - case OBXOR: u = l ^ r; break; - case OBOR: u = l | r; break; - case ONEG: u = !l; break; - case OSNEG: u = -l; break; - case OCPL: u = ~l; break; - case OAND: i = l && r; goto sign; - case OOR: i = l || r; goto sign; - case OLT: i = l < r; goto sign; - case OGT: i = l > r; goto sign; - case OGE: i = l >= r; goto sign; - case OLE: i = l <= r; goto sign; - case OEQ: i = l == r; goto sign; - case ONE: i = l != r; goto sign; - default: return 0; - } - res->u.u = u & ones(res->type->size); - - DBG("FOLD ui l=%llu %d r=%llu = %llu", l, op, r, u); - return 1; - -sign: - res->u.i = i; - - DBG("FOLD sui %llu %d %llu = %llu", l, op, r, i); - return 1; -} - -static int -foldfloat(int op, Symbol *res, TFLOAT l, TFLOAT r) -{ - TFLOAT f; - TINT i; - int (*validate)(TFLOAT, TFLOAT, Type *tp); - - switch (op) { - case OADD: validate = addf; break; - case OSUB: validate = subf; break; - case OMUL: validate = mulf; break; - case ODIV: validate = divf; break; - default: validate = NULL; break; - } - - if (validate && !(*validate)(l, r, res->type)) - return 0; - - switch (op) { - case OADD: f = l + r; break; - case OSUB: f = l - r; break; - case OMUL: f = l * r; break; - case ODIV: f = l / r; break; - case OLT: i = l < r; goto comparison; - case OGT: i = l > r; goto comparison; - case OGE: i = l >= r; goto comparison; - case OLE: i = l <= r; goto comparison; - case OEQ: i = l == r; goto comparison; - case ONE: i = l != r; goto comparison; - default: return 0; - } - res->u.f = f; - - DBG("FOLD f l=%lf %d r=%lf = %lf", l, op, r, f); - return 1; - -comparison: - res->u.i = i; - - DBG("FOLD if l=%lf %d r=%lf = %lld", l, op, r, i); - return 1; -} - -static Node * -foldconst(int type, int op, Type *tp, Symbol *ls, Symbol *rs) -{ - Symbol *sym, aux; - TINT i; - TUINT u; - TFLOAT f; - - aux.type = tp; - switch (type) { - case INT: - i = (rs) ? rs->u.i : 0; - if (!foldint(op, &aux, ls->u.i, i)) - return NULL; - break; - case UNSIGNED: - u = (rs) ? rs->u.u : 0u; - if (!folduint(op, &aux, ls->u.u, u)) - return NULL; - break; - case FLOAT: - f = (rs) ? rs->u.f : 0.0; - if (!foldfloat(op, &aux, ls->u.f, f)) - return NULL; - break; - } - sym = newsym(NS_IDEN, NULL); - sym->flags |= SCONSTANT; - sym->type = tp; - sym->u = aux.u; - return constnode(sym); -} - -static Node * -foldcast(Node *np, Node *l) -{ - TUINT negmask, mask, u; - Type *newtp = np->type, *oldtp = l->type; - Symbol aux, *sym, *osym = l->sym; - - if (!(l->flags & NCONST)) - return np; - - switch (newtp->op) { - case PTR: - case INT: - case ENUM: - switch (oldtp->op) { - case PTR: - case INT: - case ENUM: - u = (oldtp->prop & TSIGNED) ? osym->u.i : osym->u.u; - break; - case FLOAT: - oldtp = newtp; - u = osym->u.f; - break; - default: - return np; - } - mask = ones(newtp->size); - if (newtp->prop & TSIGNED) { - negmask = ~mask; - if (u & (negmask >> 1) & mask) - u |= negmask; - aux.u.i = u; - } else { - aux.u.u = u & mask; - } - break; - case FLOAT: - /* FIXME: The cast can be from another float type */ - aux.u.f = (oldtp->prop & TSIGNED) ? osym->u.i : osym->u.u; - break; - default: - return np; - } - DBG("FOLD cast %c->%c", oldtp->letter, newtp->letter); - freetree(np); - sym = newsym(NS_IDEN, NULL); - sym->flags |= SCONSTANT; - sym->type = newtp; - sym->u = aux.u; - return constnode(sym); -} - -static Node * -foldunary(Node *np, Node *l) -{ - int op = l->op; - Node *aux; - - switch (np->op) { - case ONEG: - if (l->op == ONEG) - break; - return NULL; - case OADD: - DBG("FOLD unary delete %d", np->op); - np->left = NULL; - freetree(np); - return l; - case OCAST: - if (op != OCAST) - return foldcast(np, l); - /* TODO: This is wrong: (float)(int) 7.2 */ - DBG("FOLD unary collapse %d", np->op); - np->left = l->left; - l->left = NULL; - freetree(l); - return np; - case OSNEG: - case OCPL: - if (op != np->op) - return NULL; - break; - case OPTR: - if (op != OADDR || np->type != l->left->type) - return NULL; - break; - case OADDR: - if (op != OPTR) - return NULL; - break; - default: - return NULL; - } - DBG("FOLD unary cancel %d", np->op); - aux = l->left; - l->left = NULL; - freetree(np); - return aux; -} - -static Node * -fold(Node *np) -{ - Symbol *rs, *ls; - Type *optype; - int type; - int op = np->op; - Node *p, *lp = np->left, *rp = np->right; - Type *tp = np->type; - - assert(lp && rp); - if ((op == ODIV || op == OMOD) && cmpnode(rp, 0)) { - warn("division by 0"); - return NULL; - } - /* - * Return if any of the children is no constant, - * or it is a constant generated when - * the address of a static variable is taken - * (when we don't know the physical address so - * we cannot fold it) - */ - if (!rp) { - rs = NULL; - } else { - if (!(rp->flags & NCONST) || !rp->sym) - return NULL; - rs = rp->sym; - } - - if (!(lp->flags & NCONST) || !lp->sym) - return NULL; - optype = lp->type; - ls = lp->sym; - - switch (type = optype->op) { - case ENUM: - case INT: - if (!(optype->prop & TSIGNED)) - type = UNSIGNED; - case PTR: - case FLOAT: - if ((p = foldconst(type, op, tp, ls, rs)) == NULL) - return NULL; - freetree(np); - return p; - default: - return NULL; - } -} - -static void -commutative(Node *np, Node *l, Node *r) -{ - int op = np->op; - - if (r == NULL || r->flags&NCONST || !(l->flags&NCONST)) - return; - - switch (op) { - case OLT: - case OGT: - case OGE: - case OLE: - DBG("FOLD neg commutative %d", np->op); - np->op = negop(op); - case OEQ: - case ONE: - case OADD: - case OMUL: - case OBAND: - case OBXOR: - case OBOR: - DBG("FOLD commutative %d", np->op); - np->left = r; - np->right = l; - break; - } -} - -static Node * -identity(Node *np) -{ - int iszeror, isoner; - int iszerol, isonel; - Node *lp = np->left, *rp = np->right; - - if (!rp) - return NULL; - - iszeror = cmpnode(rp, 0); - isoner = cmpnode(rp, 1), - iszerol = cmpnode(lp, 0); - isonel = cmpnode(lp, 1); - - switch (np->op) { - case OOR: - /* - * 1 || i => 1 (free right) - * i || 0 => i (free right) - * 0 || i => i (free left) - * i || 1 => i,1 (comma) - */ - if (isonel | iszeror) - goto free_right; - if (iszerol) - goto free_left; - if (isoner) - goto change_to_comma; - return NULL; - case OAND: - /* - * 0 && i => 0 (free right) - * i && 1 => i (free right) - * 1 && i => i (free left) - * i && 0 => i,0 (comma) - */ - if (iszerol | isoner) - goto free_right; - if (isonel) - goto free_left; - if (iszeror) - goto change_to_comma; - return NULL; - case OSHL: - case OSHR: - /* - * i >> 0 => i (free right) - * i << 0 => i (free right) - * 0 >> i => 0 (free right) - * 0 << i => 0 (free right) - */ - if (iszeror | iszerol) - goto free_right; - return NULL; - case OBXOR: - case OADD: - case OBOR: - case OSUB: - /* - * i + 0 => i - * i - 0 => i - * i | 0 => i - * i ^ 0 => i - */ - if (iszeror) - goto free_right; - return NULL; - case OMUL: - /* - * i * 0 => i,0 - * i * 1 => i - */ - if (iszeror) - goto change_to_comma; - if (isoner) - goto free_right; - return NULL; - case ODIV: - /* i / 1 => i */ - if (isoner) - goto free_right; - return NULL; - case OBAND: - /* i & ~0 => i */ - if (cmpnode(rp, -1)) - goto free_right; - return NULL; - case OMOD: - /* i % 1 => i,1 */ - /* TODO: i % 2^n => i & n-1 */ - if (isoner) - goto change_to_comma; - default: - return NULL; - } - -free_right: - DBG("FOLD identity %d", np->op); - np->left = NULL; - freetree(np); - return lp; - -free_left: - DBG("FOLD identity %d", np->op); - np->right = NULL; - freetree(np); - return rp; - -change_to_comma: - DBG("FOLD identity %d", np->op); - np->op = OCOMMA; - return np; -} - -static Node * -foldternary(Node *np, Node *cond, Node *body) -{ - if (!(cond->flags & NCONST)) - return np; - if (cmpnode(cond, 0)) { - np = body->right; - freetree(body->left); - } else { - np = body->left; - freetree(body->right); - } - - DBG("FOLD ternary"); - body->left = NULL; - body->right = NULL; - freetree(cond); - free(body); - return np; -} - -/* TODO: fold OCOMMA */ - -Node * -simplify(Node *np) -{ - Node *p, *l, *r; - - if (!np) - return NULL; - if (debug) - prtree(np); - - l = np->left = simplify(np->left); - r = np->right = simplify(np->right); - - switch (np->op) { - case OASK: - return foldternary(np, l, r); - case OCALL: - case OPAR: - case OSYM: - case OASSIGN: - case OA_MUL: - case OA_DIV: - case OA_MOD: - case OA_ADD: - case OA_SUB: - case OA_SHL: - case OA_SHR: - case OA_AND: - case OA_XOR: - case OA_OR: - return np; - case OSNEG: - case OCPL: - case OADDR: - case OPTR: - case INC: - case DEC: - case OCAST: - case ONEG: - assert(!r); - if ((p = foldunary(np, l)) != NULL) - return p; - return np; - default: - commutative(np, l, r); - if ((p = fold(np)) != NULL) - return p; - if ((p = identity(np)) != NULL) - return p; - return np; - } -} diff --git a/cc1/init.c b/cc1/init.c @@ -1,378 +0,0 @@ -static char sccsid[] = "@(#) ./cc1/init.c"; -#include <stdint.h> -#include <stdlib.h> -#include <string.h> - -#include <cstd.h> -#include "../inc/scc.h" -#include "cc1.h" - - -typedef struct init Init; - -struct designator { - TINT pos; - Node *expr; - struct designator *next; -}; - -struct init { - TUINT pos; - TUINT max; - struct designator *tail; - struct designator *head; -}; - -static TINT -arydesig(Type *tp, Init *ip) -{ - TINT npos; - Node *np; - - if (tp->op != ARY) - errorp("array index in non-array initializer"); - next(); - np = constexpr(); - npos = np->sym->u.i; - if (npos < 0 || (tp->prop & TDEFINED) && npos >= tp->n.elem) { - errorp("array index in initializer exceeds array bounds"); - npos = 0; - } - freetree(np); - expect(']'); - return npos; -} - -static TINT -fielddesig(Type *tp, Init *ip) -{ - int ons; - Symbol *sym, **p; - - if (!(tp->prop & TAGGREG)) - errorp("field name not in record or union initializer"); - ons = namespace; - namespace = tp->ns; - next(); - namespace = ons; - if (yytoken != IDEN) - unexpected(); - sym = yylval.sym; - next(); - if ((sym->flags & SDECLARED) == 0) { - errorp("unknown field '%s' specified in initializer", - sym->name); - return 0; - } - for (p = tp->p.fields; *p != sym; ++p) - ; - return p - tp->p.fields; -} - -static Init * -init(Init *ip) -{ - ip->tail = ip->head = NULL; - ip->pos = ip->max = 0; - return ip; -} - -static Node * -str2ary(Type *tp) -{ - Node *np; - Type *btp = tp->type;; - Symbol *sym; - size_t len; - char *s; - - np = assign(); - sym = np->left->sym; - if (btp != chartype && btp != uchartype && btp != schartype) { - errorp("array of inappropriate type initialized from string constant"); - return constnode(zero); - } - - len = sym->type->n.elem-1; - if (!(tp->prop & TDEFINED)) { - tp->n.elem = len+1; - deftype(tp); - } else if (tp->n.elem < len) { - warn("initializer-string for array of chars is too long"); - } - - len = tp->n.elem; - s = sym->u.s; - sym = newstring(NULL, len); - strncpy(sym->u.s, s, len); - np->sym = sym; - np->type = sym->type; - - return np; -} - -static Node * -initialize(Type *tp) -{ - Node *np; - Symbol *sym; - - if (tp->op == ARY && yytoken == STRING) - return str2ary(tp); - - if (yytoken == '{' || tp->op == STRUCT || tp->op == ARY) - return initlist(tp); - - np = assign(); - if (eqtype(tp, np->type, 1)) - return np; - - np = convert(decay(np), tp, 0); - if (!np) { - errorp("incorrect initializer"); - return constnode(zero); - } - - return simplify(np); -} - -static Node * -mkcompound(Init *ip, Type *tp) -{ - Node **v, **p; - size_t n; - struct designator *dp, *next; - Symbol *sym; - - if (tp->op == UNION) { - Node *np = NULL; - - v = xmalloc(sizeof(*v)); - for (dp = ip->head; dp; dp = next) { - freetree(np); - np = dp->expr; - next = dp->next; - free(dp); - } - *v = np; - } else { - n = (tp->prop&TDEFINED) ? tp->n.elem : ip->max; - if (n == 0) { - v = NULL; - } else if (n > SIZE_MAX / sizeof(*v)) { - errorp("compound literal too big"); - return constnode(zero); - } else { - n *= sizeof(*v); - v = memset(xmalloc(n), 0, n); - - for (dp = ip->head; dp; dp = next) { - p = &v[dp->pos]; - freetree(*p); - *p = dp->expr; - next = dp->next; - free(dp); - } - } - } - - sym = newsym(NS_IDEN, NULL); - sym->u.init = v; - sym->type = tp; - sym->flags |= SINITLST; - - return constnode(sym); -} - -static void -newdesig(Init *ip, Node *np) -{ - struct designator *dp; - - dp = xmalloc(sizeof(*dp)); - dp->pos = ip->pos; - dp->expr = np; - dp->next = NULL; - - if (ip->head == NULL) { - ip->head = ip->tail = dp; - } else { - ip->tail->next = dp; - ip->tail = dp; - } - - if (ip->pos+1 > ip->max) - ip->max = ip->pos+1; -} - -Node * -initlist(Type *tp) -{ - Init in; - Node *np; - Type *curtp; - int braces, scalar, toomany, outbound; - TINT nelem = tp->n.elem; - static int depth; - - if (depth == NR_SUBTYPE) - error("too many nested initializers"); - ++depth; - init(&in); - braces = scalar = toomany = 0; - - if (accept('{')) - braces = 1; - - do { - curtp = inttype; - switch (yytoken) { - case '[': - in.pos = arydesig(tp, &in); - curtp = tp->type; - goto desig_list; - case '.': - in.pos = fielddesig(tp, &in); - if (in.pos < nelem) - curtp = tp->p.fields[in.pos]->type; - desig_list: - if (yytoken == '[' || yytoken == '.') { - np = initlist(curtp); - goto new_desig; - } - expect('='); - default: - outbound = 0; - - switch (tp->op) { - case ARY: - curtp = tp->type; - if (!(tp->prop & TDEFINED) || in.pos < tp->n.elem) - break; - if (!toomany) - warn("excess elements in array initializer"); - toomany = 1; - outbound = 1; - break; - case UNION: - case STRUCT: - if (in.pos < nelem) { - curtp = tp->p.fields[in.pos]->type; - break; - } - if (!toomany) - warn("excess elements in struct initializer"); - toomany = 1; - outbound = 1; - break; - default: - curtp = tp; - if (!scalar) - warn("braces around scalar initializer"); - scalar = 1; - if (in.pos == 0) - break; - if (!toomany) - warn("excess elements in scalar initializer"); - toomany = 1; - outbound = 1; - break; - } - np = initialize(curtp); - if (outbound) { - freetree(np); - np = NULL; - } - } - -new_desig: - if (np) - newdesig(&in, np); - if (++in.pos == 0) - errorp("compound literal too big"); - if (nelem == in.pos && !braces) - break; - } while (accept(',')); - - if (braces) - expect('}'); - - - if (tp->op == ARY && !(tp->prop & TDEFINED)) { - tp->n.elem = in.max; - deftype(tp); - } - if (in.max == 0) { - errorp("empty braced initializer"); - return constnode(zero); - } - - return mkcompound(&in, tp); -} - -static void -autoinit(Symbol *sym, Node *np) -{ - Symbol *hidden; - Type *tp = sym->type; - size_t n; /* FIXME: It should be SIZET */ - -repeat: - switch (tp->op) { - case UNION: - np = np->sym->u.init[0]; - tp = np->type; - goto repeat; - case ARY: - case STRUCT: - if (!(np->flags & NCONST)) - abort(); /* TODO */ - hidden = newsym(NS_IDEN, NULL); - hidden->type = sym->type; - hidden->flags |= SLOCAL | SHASINIT; - emit(ODECL, hidden); - emit(OINIT, np); - emit(ODECL, sym); - emit(OEXPR, - node(OASSIGN, tp, varnode(sym), varnode(hidden))); - break; - default: - emit(ODECL, sym); - np = node(OASSIGN, tp, varnode(sym), np); - emit(OEXPR, np); - break; - } -} - -void -initializer(Symbol *sym, Type *tp) -{ - Node *np; - int flags = sym->flags; - - if (tp->op == FTN) { - errorp("function '%s' initialized like a variable", - sym->name); - tp = inttype; - } - np = initialize(tp); - - if (flags & SDEFINED) { - errorp("redeclaration of '%s'", sym->name); - } else if ((flags & (SGLOBAL|SLOCAL|SPRIVATE)) != 0) { - if (!(np->flags & NCONST)) { - errorp("initializer element is not constant"); - return; - } - sym->flags |= SHASINIT; - sym->flags &= ~SEMITTED; - emit(ODECL, sym); - emit(OINIT, np); - sym->flags |= SDEFINED; - } else if ((flags & (SEXTERN|STYPEDEF)) != 0) { - errorp("'%s' has both '%s' and initializer", - sym->name, (flags&SEXTERN) ? "extern" : "typedef"); - } else { - autoinit(sym, np); - } -} diff --git a/cc1/lex.c b/cc1/lex.c @@ -1,801 +0,0 @@ -static char sccsid[] = "@(#) ./cc1/lex.c"; -#include <assert.h> -#include <ctype.h> -#include <errno.h> -#include <limits.h> -#include <setjmp.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include <cstd.h> -#include "../inc/scc.h" -#include "cc1.h" - -int yytoken; -struct yystype yylval; -char yytext[STRINGSIZ+3]; -unsigned short yylen; -int lexmode = CCMODE; -unsigned lineno; -char filenam[FILENAME_MAX]; - -int namespace = NS_IDEN; -static int safe; -Input *input; - -void -ilex(void) -{ - static struct keyword keys[] = { - {"auto", SCLASS, AUTO}, - {"break", BREAK, BREAK}, - {"_Bool", TYPE, BOOL}, - {"__builtin_va_list", TYPE, VA_LIST}, - {"case", CASE, CASE}, - {"char", TYPE, CHAR}, - {"const", TQUALIFIER, CONST}, - {"continue", CONTINUE, CONTINUE}, - {"default", DEFAULT, DEFAULT}, - {"do", DO, DO}, - {"double", TYPE, DOUBLE}, - {"else", ELSE, ELSE}, - {"enum", TYPE, ENUM}, - {"extern", SCLASS, EXTERN}, - {"float", TYPE, FLOAT}, - {"for", FOR, FOR}, - {"goto", GOTO, GOTO}, - {"if", IF, IF}, - {"inline", TQUALIFIER, INLINE}, - {"int", TYPE, INT}, - {"long", TYPE, LONG}, - {"register", SCLASS, REGISTER}, - {"restrict", TQUALIFIER, RESTRICT}, - {"return", RETURN, RETURN}, - {"short", TYPE, SHORT}, - {"signed", TYPE, SIGNED}, - {"sizeof", SIZEOF, SIZEOF}, - {"static", SCLASS, STATIC}, - {"struct", TYPE, STRUCT}, - {"switch", SWITCH, SWITCH}, - {"typedef", SCLASS, TYPEDEF}, - {"union", TYPE, UNION}, - {"unsigned", TYPE, UNSIGNED}, - {"void", TYPE, VOID}, - {"volatile", TQUALIFIER, VOLATILE}, - {"while", WHILE, WHILE}, - {NULL, 0, 0}, - }; - keywords(keys, NS_KEYWORD); -} - -void -setloc(char *fname, unsigned line) -{ - size_t len; - - if ((len = strlen(fname)) >= FILENAME_MAX) - die("cc1: %s: file name too long", fname); - memmove(filenam, fname, len); - filenam[len] = '\0'; - - free(input->filenam); - input->filenam = xstrdup(fname); - lineno = input->lineno = line; -} - -void -addinput(char *fname, Symbol *hide, char *buffer) -{ - FILE *fp; - char *extp; - unsigned flags; - int infileln; - Input *newip, *curip = input; - - if (hide) { - /* this is a macro expansion */ - fp = NULL; - if (hide->hide == UCHAR_MAX) - die("cc1: too many macro expansions"); - ++hide->hide; - flags = IMACRO; - } else if (fname) { - /* a new file */ - if ((fp = fopen(fname, "r")) == NULL) - die("cc1: %s: %s", fname, strerror(errno)); - flags = IFILE; - if (curip && onlyheader) { - infileln = strlen(infile); - if (extp = strrchr(infile, '.')) - infileln -= strlen(extp); - printf("%.*s.o: %s %s\n", - infileln, infile, infile, fname); - } - } else { - /* reading from stdin */ - fp = stdin; - fname = "<stdin>"; - flags = ISTDIN; - } - - newip = xmalloc(sizeof(*newip)); - - if (!buffer) { - buffer = xmalloc(INPUTSIZ); - buffer[0] = '\0'; - } - - if (curip) - curip->lineno = lineno; - - newip->p = newip->begin = newip->line = buffer; - newip->filenam = NULL; - newip->lineno = 0; - newip->next = curip; - newip->fp = fp; - newip->hide = hide; - newip->flags = flags; - input = newip; - - setloc(fname, (curip) ? curip->lineno : newip->lineno); -} - -void -delinput(void) -{ - Input *ip = input; - Symbol *hide = ip->hide; - - switch (ip->flags & ITYPE) { - case IFILE: - if (fclose(ip->fp)) - die("cc1: %s: %s", ip->filenam, strerror(errno)); - break; - case IMACRO: - assert(hide->hide == 1); - --hide->hide; - break; - } - input = ip->next; - free(ip->filenam); - free(ip->line); - if (input) { - lineno = input->lineno; - strcpy(filenam, input->filenam); - } -} - -static void -newline(void) -{ - if (++lineno == 0) - die("cc1: %s: file too long", filenam); -} - -/* - * Read the next character from the input file, counting number of lines - * and joining lines escaped with \ - */ -static int -readchar(void) -{ - FILE *fp = input->fp; - int c; - -repeat: - switch (c = getc(fp)) { - case '\\': - if ((c = getc(fp)) == '\n') { - newline(); - goto repeat; - } - ungetc(c, fp); - c = '\\'; - break; - case '\n': - newline(); - break; - default: - if (!isprint(c) && !ispunct(c) && !isspace(c)) - warn("invalid input character. The shame of UB is yours"); - break; - } - - return c; -} - -/* - * discard a C comment. This function is only called from readline - * because it is impossible to have a comment in a macro, because - * comments are always discarded before processing any cpp directive - */ -static void -comment(int type) -{ - int c; - -repeat: - while ((c = readchar()) != EOF && c != type) - ; - - if (c == EOF) { - errorp("unterminated comment"); - return; - } - - if (type == '*' && (c = readchar()) != '/') - goto repeat; -} - -/* - * readline is used to read a full logic line from a file. - * It discards comments and check that the line fits in - * the input buffer - */ -static int -readline(void) -{ - char *bp, *lim; - int c, peekc = 0; - - if (feof(input->fp)) { - input->flags |= IEOF; - return 0; - } - - *input->line = '\0'; - lim = &input->line[INPUTSIZ-1]; - for (bp = input->line; bp < lim-1; *bp++ = c) { - c = (peekc) ? peekc : readchar(); - peekc = 0; - if (c == '\n' || c == EOF) - break; - if (c != '/') - continue; - - /* check for /* or // */ - peekc = readchar(); - if (peekc != '*' && peekc != '/') - continue; - comment((peekc == '/') ? '\n' : '*'); - peekc = 0; - c = ' '; - } - - input->begin = input->p = input->line; - if (bp == lim-1) { - errorp("line too long"); - --bp; - } - *bp++ = '\n'; - *bp = '\0'; - - return 1; -} - -/* - * moreinput gets more bytes to be passed to the lexer. - * It can take more bytes from macro expansions or - * directly reading from files. When a cpp directive - * is processed the line is discarded because it must not - * be passed to the lexer - */ -static int -moreinput(void) -{ - int wasexpand = 0; - -repeat: - if (!input) - return 0; - - if (*input->p == '\0') { - if ((input->flags&ITYPE) == IMACRO) { - wasexpand = 1; - input->flags |= IEOF; - } - if (input->flags & IEOF) { - delinput(); - goto repeat; - } - if (!readline() || cpp()) { - *input->p = '\0'; - goto repeat; - } - } - - if (onlycpp && !wasexpand) - ppragmaln(); - return 1; -} - -static void -tok2str(void) -{ - if ((yylen = input->p - input->begin) > INTIDENTSIZ) - error("token too big"); - memcpy(yytext, input->begin, yylen); - yytext[yylen] = '\0'; - input->begin = input->p; -} - -static Symbol * -readint(char *s, int base, int sign, Symbol *sym) -{ - Type *tp = sym->type; - struct limits *lim; - TUINT u, val, max; - int c; - - lim = getlimits(tp); - max = lim->max.i; - if (*s == '0') - ++s; - if (toupper(*s) == 'X') - ++s; - - for (u = 0; isxdigit(c = *s++); u = u*base + val) { - static char letters[] = "0123456789ABCDEF"; - val = strchr(letters, toupper(c)) - letters; - repeat: - if (u <= max/base && u*base <= max - val) - continue; - if (tp->prop & TSIGNED) { - if (tp == inttype) - tp = (base==10) ? longtype : uinttype; - else if (tp == longtype) - tp = (base==10) ? llongtype : ulongtype; - else - goto overflow; - } else { - if (tp == uinttype) - tp = (sign==UNSIGNED) ? ulongtype : longtype; - else if (tp == ulongtype) - tp = (sign==UNSIGNED) ? ullongtype : llongtype; - else - goto overflow; - } - sym->type = tp; - lim = getlimits(tp); - max = lim->max.i; - goto repeat; - } - - if (tp->prop & TSIGNED) - sym->u.i = u; - else - sym->u.u = u; - - return sym; - -overflow: - errorp("overflow in integer constant"); - return sym; -} - -static int -integer(char *s, int base) -{ - Type *tp; - Symbol *sym; - unsigned size, sign; - - for (size = sign = 0; ; ++input->p) { - switch (toupper(*input->p)) { - case 'L': - if (size == LLONG) - goto wrong_type; - size = (size == LONG) ? LLONG : LONG; - continue; - case 'U': - if (sign == UNSIGNED) - goto wrong_type; - sign = UNSIGNED; - continue; - default: - goto convert; - wrong_type: - error("invalid suffix in integer constant"); - } - } - -convert: - tp = ctype(INT, sign, size); - sym = newsym(NS_IDEN, NULL); - sym->type = tp; - sym->flags |= SCONSTANT; - yylval.sym = readint(s, base, sign, sym); - return CONSTANT; -} - -static char * -digits(int base) -{ - char *p; - int c; - - for (p = input->p; c = *p; ++p) { - switch (base) { - case 8: - if (!strchr("01234567", c)) - goto end; - break; - case 10: - if (!isdigit(c)) - goto end; - break; - case 16: - if (!isxdigit(c)) - goto end; - break; - } - } -end: - input->p = p; - tok2str(); - return yytext; -} - -static int -number(void) -{ - int base; - - if (*input->p != '0') { - base = 10; - } else { - if (toupper(*++input->p) == 'X') { - ++input->p; - base = 16; - } else { - base = 8; - } - } - - return integer(digits(base), base); -} - -static int -escape(void) -{ - int c, base; - - switch (*++input->p) { - case 'a': return '\a'; - case 'f': return '\f'; - case 'n': return '\n'; - case 'r': return '\r'; - case 't': return '\t'; - case 'v': return '\v'; - case '"': return '"'; - case '\'': return '\''; - case '\\': return '\\'; - case '\?': return '\?'; - case 'u': - /* - * FIXME: universal constants are not correctly handled - */ - if (!isdigit(*++input->p)) - warn("incorrect digit for numerical character constant"); - base = 10; - break; - case 'x': - if (!isxdigit(*++input->p)) - warn("\\x used with no following hex digits"); - base = 16; - break; - case '0': - if (!strchr("01234567", *++input->p)) - warn("\\0 used with no following octal digits"); - base = 8; - break; - default: - warn("unknown escape sequence"); - return ' '; - } - errno = 0; - c = strtoul(input->p, &input->p, base); - if (errno || c > 255) - warn("character constant out of range"); - --input->p; - return c; -} - -static int -character(void) -{ - int c; - Symbol *sym; - - if ((c = *++input->p) == '\\') - c = escape(); - else - c = *input->p; - ++input->p; - if (*input->p != '\'') - errorp("invalid character constant"); - else - ++input->p; - - sym = newsym(NS_IDEN, NULL); - sym->u.i = c; - sym->type = inttype; - yylval.sym = sym; - tok2str(); - return CONSTANT; -} - -static int -string(void) -{ - char *bp = yytext; - int c; - - *bp++ = '"'; - for (++input->p; (c = *input->p) != '"'; ++input->p) { - if (c == '\0') { - errorp("missing terminating '\"' character"); - break; - } - if (c == '\\') - c = escape(); - if (bp == &yytext[STRINGSIZ+1]) { - /* TODO: proper error handling here */ - error("string too long"); - } - *bp++ = c; - } - - input->begin = ++input->p; - *bp = '\0'; - - yylen = bp - yytext + 1; - yylval.sym = newstring(yytext+1, yylen-1); - *bp++ = '"'; - *bp = '\0'; - return STRING; -} - -static int -iden(void) -{ - Symbol *sym; - char *p, *begin; - - begin = input->p; - for (p = begin; isalnum(*p) || *p == '_'; ++p) - ; - input->p = p; - tok2str(); - if ((sym = lookup(NS_CPP, yytext, NOALLOC)) != NULL) { - if (!disexpand && !sym->hide && expand(begin, sym)) - return next(); - } - sym = lookup(namespace, yytext, ALLOC); - yylval.sym = sym; - if (sym->flags & SCONSTANT) - return CONSTANT; - if (sym->token != IDEN) - yylval.token = sym->u.token; - return sym->token; -} - -static int -follow(int expect, int ifyes, int ifno) -{ - if (*input->p++ == expect) - return ifyes; - --input->p; - return ifno; -} - -static int -minus(void) -{ - switch (*input->p++) { - case '-': return DEC; - case '>': return INDIR; - case '=': return SUB_EQ; - default: --input->p; return '-'; - } -} - -static int -plus(void) -{ - switch (*input->p++) { - case '+': return INC; - case '=': return ADD_EQ; - default: --input->p; return '+'; - } -} - -static int -relational(int op, int equal, int shift, int assig) -{ - int c; - - if ((c = *input->p++) == '=') - return equal; - if (c == op) - return follow('=', assig, shift); - --input->p; - return op; -} - -static int -logic(int op, int equal, int logic) -{ - int c; - - if ((c = *input->p++) == '=') - return equal; - if (c == op) - return logic; - --input->p; - return op; -} - -static int -dot(void) -{ - int c; - - if ((c = *input->p) != '.') - return '.'; - if ((c = *++input->p) != '.') - error("incorrect token '..'"); - ++input->p; - return ELLIPSIS; -} - -static int -operator(void) -{ - int t; - - switch (t = *input->p++) { - case '<': t = relational('<', LE, SHL, SHL_EQ); break; - case '>': t = relational('>', GE, SHR, SHR_EQ); break; - case '&': t = logic('&', AND_EQ, AND); break; - case '|': t = logic('|', OR_EQ, OR); break; - case '=': t = follow('=', EQ, '='); break; - case '^': t = follow('=', XOR_EQ, '^'); break; - case '*': t = follow('=', MUL_EQ, '*'); break; - case '/': t = follow('=', DIV_EQ, '/'); break; - case '!': t = follow('=', NE, '!'); break; - case '#': t = follow('#', '$', '#'); break; - case '-': t = minus(); break; - case '+': t = plus(); break; - case '.': t = dot(); break; - } - tok2str(); - return t; -} - -/* TODO: Ensure that namespace is NS_IDEN after a recovery */ - -/* - * skip all the spaces until the next token. When we are in - * CPPMODE \n is not considered a whitespace - */ -static int -skipspaces(void) -{ - int c; - - for (;;) { - switch (c = *input->p) { - case '\n': - if (lexmode == CPPMODE) - goto return_byte; - ++input->p; - case '\0': - if (!moreinput()) - return EOF; - break; - case ' ': - case '\t': - case '\v': - case '\r': - case '\f': - ++input->p; - break; - default: - goto return_byte; - } - } - -return_byte: - input->begin = input->p; - return c; -} - -int -next(void) -{ - int c; - - if ((c = skipspaces()) == EOF) - yytoken = EOFTOK; - else if (isalpha(c) || c == '_') - yytoken = iden(); - else if (isdigit(c)) - yytoken = number(); - else if (c == '"') - yytoken = string(); - else if (c == '\'') - yytoken = character(); - else - yytoken = operator(); - - if (yytoken == EOF) { - strcpy(yytext, "<EOF>"); - if (cppctx) - errorp("#endif expected"); - } - - DBG("TOKEN %s", yytext); - return yytoken; -} - -void -expect(int tok) -{ - if (yytoken != tok) { - if (isgraph(tok)) - errorp("expected '%c' before '%s'", tok, yytext); - else - errorp("unexpected '%s'", yytext); - } else { - next(); - } -} - -int -ahead(void) -{ - skipspaces(); - return *input->begin; -} - -void -setsafe(int type) -{ - safe = type; -} - -void -discard(void) -{ - extern jmp_buf recover; - int c; - - input->begin = input->p; - for (c = yytoken; ; c = *input->begin++) { - switch (safe) { - case END_COMP: - if (c == '}') - goto jump; - goto semicolon; - case END_COND: - if (c == ')') - goto jump; - break; - case END_LDECL: - if (c == ',') - goto jump; - case END_DECL: - semicolon: - if (c == ';') - goto jump; - break; - } - if (c == '\0' && !moreinput()) - exit(1); - } -jump: - yytoken = c; - longjmp(recover, 1); -} diff --git a/cc1/main.c b/cc1/main.c @@ -1,102 +0,0 @@ -static char sccsid[] = "@(#) ./cc1/main.c"; -#include <setjmp.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> - -#include "../inc/arg.h" -#include "../inc/scc.h" -#include "cc1.h" - -char *argv0, *infile; - -int warnings; -jmp_buf recover; - -static struct items uflags; -int onlycpp, onlyheader; - - -extern int failure; - -static void -defmacro(char *macro) -{ - char *p = strchr(macro, '='); - - if (p) - *p++ = '\0'; - else - p = "1"; - - defdefine(macro, p, "command-line"); -} - -static void -usage(void) -{ - fputs("usage: cc1 [-Ewd] [-D def[=val]]... [-U def]... " - "[-I dir]... [-o output] [input]\n", stderr); - exit(1); -} - -int -main(int argc, char *argv[]) -{ - int i; - - ilex(); - icpp(); - icode(); - ibuilts(); - - ARGBEGIN { - case 'D': - defmacro(EARGF(usage())); - break; - case 'M': - onlyheader = 1; - break; - case 'E': - onlycpp = 1; - break; - case 'I': - incdir(EARGF(usage())); - break; - case 'U': - newitem(&uflags, EARGF(usage())); - break; - case 'd': - DBGON(); - break; - case 'w': - warnings = 1; - break; - default: - usage(); - } ARGEND - - if (argc > 1) - usage(); - - for (i = 0; i < uflags.n; ++i) - undefmacro(uflags.s[i]); - - infile = (*argv) ? *argv : "<stdin>"; - addinput(*argv, NULL, NULL); - - /* - * we cannot initialize arch until we have an - * output stream, because we maybe want to emit new types - */ - iarch(); - if (onlycpp || onlyheader) { - outcpp(); - } else { - for (next(); yytoken != EOFTOK; decl()) - ; - } - - return failure; -} diff --git a/cc1/stmt.c b/cc1/stmt.c @@ -1,386 +0,0 @@ -static char sccsid[] = "@(#) ./cc1/stmt.c"; -#include <stddef.h> -#include <setjmp.h> - -#include <cstd.h> -#include "../inc/scc.h" -#include "cc1.h" - -#define NEGATE 1 -#define NONEGATE 0 - -Symbol *curfun; - -static void stmt(Symbol *lbreak, Symbol *lcont, Switch *lswitch); - -static void -label(void) -{ - Symbol *sym; - - switch (yytoken) { - case IDEN: - case TYPEIDEN: - sym = lookup(NS_LABEL, yytext, ALLOC); - if (sym->flags & SDEFINED) - error("label '%s' already defined", yytext); - if ((sym->flags & SDECLARED) == 0) - sym = install(NS_LABEL, sym); - sym->flags |= SDEFINED; - emit(OLABEL, sym); - next(); - expect(':'); - break; - default: - unexpected(); - } -} - -static void -stmtexp(Symbol *lbreak, Symbol *lcont, Switch *lswitch) -{ - Node *np; - - if (accept(';')) - return; - if (yytoken == IDEN && ahead() == ':') { - label(); - stmt(lbreak, lcont, lswitch); - return; - } - np = expr(); - if ((np->flags & NEFFECT) == 0) - warn("expression without side effects"); - emit(OEXPR, np); - expect(';'); -} - -static Node * -condition(int neg) -{ - Node *np; - - expect('('); - np = condexpr(neg); - expect(')'); - - return np; -} - -static void -While(Symbol *lbreak, Symbol *lcont, Switch *lswitch) -{ - Symbol *begin; - Node *np; - - begin = newlabel(); - lcont = newlabel(); - lbreak = newlabel(); - - expect(WHILE); - np = condition(NONEGATE); - - emit(OJUMP, lcont); - - emit(OBLOOP, NULL); - emit(OLABEL, begin); - stmt(lbreak, lcont, lswitch); - emit(OLABEL, lcont); - emit(OBRANCH, begin); - emit(OEXPR, np); - emit(OELOOP, NULL); - - emit(OLABEL, lbreak); -} - -static void -For(Symbol *lbreak, Symbol *lcont, Switch *lswitch) -{ - Symbol *begin, *cond; - Node *econd, *einc; - - begin = newlabel(); - lcont = newlabel(); - cond = newlabel(); - lbreak = newlabel(); - - pushctx(); - - expect(FOR); - expect('('); - switch (yytoken) { - case TYPE: - case TYPEIDEN: - case TQUALIFIER: - case SCLASS: - decl(); - break; - default: - emit(OEXPR, expr()); - case ';': - expect(';'); - break; - } - econd = (yytoken != ';') ? condexpr(NONEGATE) : NULL; - expect(';'); - einc = (yytoken != ')') ? expr() : NULL; - expect(')'); - - emit(OJUMP, cond); - - emit(OBLOOP, NULL); - emit(OLABEL, begin); - stmt(lbreak, lcont, lswitch); - emit(OLABEL, lcont); - emit(OEXPR, einc); - emit(OLABEL, cond); - emit((econd) ? OBRANCH : OJUMP, begin); - emit(OEXPR, econd); - emit(OELOOP, NULL); - - emit(OLABEL, lbreak); - - popctx(); -} - -static void -Dowhile(Symbol *lbreak, Symbol *lcont, Switch *lswitch) -{ - Symbol *begin; - Node *np; - - begin = newlabel(); - lcont = newlabel(); - lbreak = newlabel(); - - expect(DO); - - emit(OBLOOP, NULL); - emit(OLABEL, begin); - stmt(lbreak, lcont, lswitch); - expect(WHILE); - np = condition(NONEGATE); - emit(OLABEL, lcont); - emit(OBRANCH, begin); - emit(OEXPR, np); - emit(OELOOP, NULL); - - emit(OLABEL, lbreak); -} - -static void -Return(Symbol *lbreak, Symbol *lcont, Switch *lswitch) -{ - Node *np; - Type *tp = curfun->type->type; - - expect(RETURN); - np = (yytoken != ';') ? decay(expr()) : NULL; - expect(';'); - if (!np) { - if (tp != voidtype) - warn("function returning non void returns no value"); - tp = voidtype; - } else if (np->type != tp) { - if (tp == voidtype) - warn("function returning void returns a value"); - else if ((np = convert(np, tp, 0)) == NULL) - errorp("incorrect type in return"); - } - emit(ORET, NULL); - emit(OEXPR, np); -} - -static void -Break(Symbol *lbreak, Symbol *lcont, Switch *lswitch) -{ - expect(BREAK); - if (!lbreak) { - errorp("break statement not within loop or switch"); - } else { - emit(OJUMP, lbreak); - expect(';'); - } -} - -static void -Continue(Symbol *lbreak, Symbol *lcont, Switch *lswitch) -{ - expect(CONTINUE); - if (!lcont) { - errorp("continue statement not within loop"); - } else { - emit(OJUMP, lcont); - expect(';'); - } -} - -static void -Goto(Symbol *lbreak, Symbol *lcont, Switch *lswitch) -{ - Symbol *sym; - - namespace = NS_LABEL; - next(); - namespace = NS_IDEN; - - if (yytoken != IDEN) - unexpected(); - sym = yylval.sym; - if ((sym->flags & SDECLARED) == 0) - sym = install(NS_LABEL, sym); - sym->flags |= SUSED; - emit(OJUMP, sym); - next(); - expect(';'); -} - -static void -Swtch(Symbol *obr, Symbol *lcont, Switch *osw) -{ - Switch sw = {0}; - Node *cond; - Symbol *lbreak; - - expect(SWITCH); - - expect ('('); - if ((cond = convert(expr(), inttype, 0)) == NULL) { - errorp("incorrect type in switch statement"); - cond = constnode(zero); - } - expect (')'); - - lbreak = newlabel(); - emit(OBSWITCH, NULL); - emit(OEXPR, cond); - stmt(lbreak, lcont, &sw); - emit(OESWITCH, lbreak); - emit(OLABEL, lbreak); -} - -static void -Case(Symbol *lbreak, Symbol *lcont, Switch *sw) -{ - Node *np; - Symbol *label; - - expect(CASE); - if ((np = constexpr()) == NULL) - errorp("case label does not reduce to an integer constant"); - if (!sw) { - errorp("case label not within a switch statement"); - } else if (sw->nr >= 0 && ++sw->nr == NR_SWITCH) { - errorp("too many case labels for a switch statement"); - sw->nr = -1; - } - expect(':'); - - label = newlabel(); - emit(OCASE, label); - emit(OEXPR, np); - emit(OLABEL, label); - stmt(lbreak, lcont, sw); -} - -static void -Default(Symbol *lbreak, Symbol *lcont, Switch *sw) -{ - Symbol *label = newlabel(); - - if (sw->hasdef) - errorp("multiple default labels in one switch"); - sw->hasdef = 1; - expect(DEFAULT); - expect(':'); - emit(ODEFAULT, label); - emit(OLABEL, label); - stmt(lbreak, lcont, sw); -} - -static void -If(Symbol *lbreak, Symbol *lcont, Switch *lswitch) -{ - Symbol *end, *lelse; - Node *np; - - lelse = newlabel(); - expect(IF); - np = condition(NEGATE); - emit(OBRANCH, lelse); - emit(OEXPR, np); - stmt(lbreak, lcont, lswitch); - if (accept(ELSE)) { - end = newlabel(); - emit(OJUMP, end); - emit(OLABEL, lelse); - stmt(lbreak, lcont, lswitch); - emit(OLABEL, end); - } else { - emit(OLABEL, lelse); - } -} - -static void -blockit(Symbol *lbreak, Symbol *lcont, Switch *lswitch) -{ - switch (yytoken) { - case TYPEIDEN: - if (ahead() == ':') - goto parse_stmt; - case TYPE: - case TQUALIFIER: - case SCLASS: - decl(); - return; - default: - parse_stmt: - stmt(lbreak, lcont, lswitch); - } -} - -void -compound(Symbol *lbreak, Symbol *lcont, Switch *lswitch) -{ - static int nested; - - pushctx(); - expect('{'); - - if (nested == NR_BLOCK) - error("too many nesting levels of compound statements"); - - ++nested; - for (;;) { - if (yytoken == '}') - break; - blockit(lbreak, lcont, lswitch); - } - --nested; - - popctx(); - expect('}'); -} - -static void -stmt(Symbol *lbreak, Symbol *lcont, Switch *lswitch) -{ - void (*fun)(Symbol *, Symbol *, Switch *); - - switch (yytoken) { - case '{': fun = compound; break; - case RETURN: fun = Return; break; - case WHILE: fun = While; break; - case FOR: fun = For; break; - case DO: fun = Dowhile; break; - case IF: fun = If; break; - case BREAK: fun = Break; break; - case CONTINUE: fun = Continue; break; - case GOTO: fun = Goto; break; - case SWITCH: fun = Swtch; break; - case CASE: fun = Case; break; - case DEFAULT: fun = Default; break; - default: fun = stmtexp; break; - } - (*fun)(lbreak, lcont, lswitch); -} diff --git a/cc1/symbol.c b/cc1/symbol.c @@ -1,353 +0,0 @@ -static char sccsid[] = "@(#) ./cc1/symbol.c"; -#include <assert.h> -#include <limits.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include <cstd.h> -#include "../inc/scc.h" -#include "cc1.h" - -#define NR_SYM_HASH 64 -#define NR_CPP_HASH 32 -#define NR_LBL_HASH 16 - -unsigned curctx; -static unsigned short counterid; - -static Symbol *head, *labels; -static Symbol *htab[NR_SYM_HASH]; -static Symbol *htabcpp[NR_CPP_HASH]; -static Symbol *htablbl[NR_LBL_HASH]; - -#ifndef NDEBUG -void -dumpstab(Symbol **tbl, char *msg) -{ - Symbol **bp, *sym; - unsigned size; - - fprintf(stderr, "Symbol Table dump at ctx=%u\n%s\n", curctx, msg); - if (tbl == htab) - size = NR_SYM_HASH; - else if (tbl == htabcpp) - size = NR_CPP_HASH; - else if (tbl == htablbl) - size = NR_LBL_HASH; - else - abort(); - - for (bp = tbl; bp < &tbl[size]; ++bp) { - if (*bp == NULL) - continue; - fprintf(stderr, "%d", (int) (bp - htab)); - for (sym = *bp; sym; sym = sym->hash) - fprintf(stderr, "->[%d,%d:'%s'=%p]", - sym->ns, sym->ctx, sym->name, (void *) sym); - putc('\n', stderr); - } - fputs("head:", stderr); - for (sym = head; sym; sym = sym->next) { - fprintf(stderr, "->[%d,%d:'%s'=%p]", - sym->ns, sym->ctx, - (sym->name) ? sym->name : "", (void *) sym); - } - fputs("\nlabels:", stderr); - for (sym = labels; sym; sym = sym->next) { - fprintf(stderr, "->[%d,%d:'%s'=%p]", - sym->ns, sym->ctx, - (sym->name) ? sym->name : "", (void *) sym); - } - putc('\n', stderr); -} -#endif - -static Symbol ** -hash(char *s, int ns) -{ - unsigned c, h, size; - Symbol **tab; - - for (h = 0; c = *s; ++s) - h = h*33 ^ c; - - switch (ns) { - case NS_CPP: - tab = htabcpp; - size = NR_CPP_HASH-1; - break; - case NS_LABEL: - tab = htablbl; - size = NR_LBL_HASH-1; - break; - default: - tab = htab; - size = NR_SYM_HASH-1; - break; - } - return &tab[h & size]; -} - -static void -unlinkhash(Symbol *sym) -{ - Symbol **h; - - if ((sym->flags & SDECLARED) == 0) - return; - h = hash(sym->name, sym->ns); - assert(sym->ns == NS_CPP || *h == sym); - while (*h != sym) - h = &(*h)->hash; - *h = sym->hash; -} - -void -pushctx(void) -{ - DBG("SYM: pushed context %d", curctx+1); - if (++curctx == NR_BLOCK+1) - error("too many nested blocks"); -} - -void -killsym(Symbol *sym) -{ - short f; - char *name; - - if (!sym) - return; - f = sym->flags; - if (f & SSTRING) - free(sym->u.s); - if (sym->ns == NS_TAG) - sym->type->prop &= ~TDEFINED; - unlinkhash(sym); - if ((name = sym->name) != NULL) { - switch (sym->ns) { - case NS_LABEL: - if ((f & SDEFINED) == 0) - errorp("label '%s' is not defined", name); - case NS_IDEN: - if ((f & (SUSED|SGLOBAL|SDECLARED)) == SDECLARED) - warn("'%s' defined but not used", name); - break; - } - } - free(name); - free(sym); -} - -void -popctx(void) -{ - Symbol *next, *sym; - int ns, dangling = 0; - - DBG("SYM: poped context %d", curctx); - /* - * we have to be careful before popping the current - * context, because since the parser is one token - * ahead it may already have read an identifier at - * this point, and yylval.sym is a pointer to - * the symbol associated to such token. If that - * symbol is from the context that we are popping - * then we are going to generate a dangling pointer. - * We can detect this situation and call again to - * lookup. - */ - if ((yytoken == IDEN || yytoken == TYPEIDEN) && - yylval.sym->ctx == curctx) { - ns = yylval.sym->ns; - dangling = 1; - } - - for (sym = head; sym && sym->ctx == curctx; sym = next) { - /* - * Since we are unlinking them in the inverse order - * we do know that sym is always the head of the - * collision list - */ - next = sym->next; - killsym(sym); - } - head = sym; - - if (--curctx == GLOBALCTX) { - for (sym = labels; sym; sym = next) { - next = sym->next; - killsym(sym); - } - labels = NULL; - } - - if (dangling) { - yylval.sym = lookup(ns, yytext, ALLOC); - yytoken = yylval.sym->token; - } -} - -unsigned -newid(void) -{ - unsigned short id; - - if (lexmode == CPPMODE) - return 0; - id = ++counterid; - if (id == 0) { - die("cc1: overflow in %s identifiers", - (curctx) ? "internal" : "external"); - } - return id; -} - -Symbol * -newsym(int ns, char *name) -{ - Symbol *sym; - - sym = xmalloc(sizeof(*sym)); - if (name) - name = xstrdup(name); - sym->name = name; - sym->id = 0; - sym->hide = 0; - sym->ns = ns; - sym->ctx = curctx; - sym->token = IDEN; - sym->flags = 0; - sym->u.s = NULL; - sym->type = NULL; - sym->hash = NULL; - - if (ns == NS_LABEL) { - sym->next = labels; - labels = sym; - } else if (ns != NS_CPP) { - sym->next = head; - head = sym; - } - return sym; -} - -static Symbol * -linkhash(Symbol *sym) -{ - Symbol **h; - - h = hash(sym->name, sym->ns); - sym->hash = *h; - *h = sym; - - if (sym->ns != NS_CPP) - sym->id = newid(); - sym->flags |= SDECLARED; - return sym; -} - -Symbol * -newstring(char *s, size_t len) -{ - Symbol *sym = newsym(NS_IDEN, NULL); - - if (lexmode != CPPMODE) - sym->type = mktype(chartype, ARY, len, NULL); - sym->id = newid(); - sym->flags |= SSTRING | SCONSTANT | SPRIVATE; - sym->u.s = xmalloc(len); - if (s) - memcpy(sym->u.s, s, len); - - return sym; -} - -Symbol * -newlabel(void) -{ - Symbol *sym = newsym(NS_LABEL, NULL); - sym->id = newid(); - return sym; -} - -Symbol * -lookup(int ns, char *name, int alloc) -{ - Symbol *sym; - int sns, c; - char *t; - - c = *name; - for (sym = *hash(name, ns); sym; sym = sym->hash) { - t = sym->name; - if (*t != c || strcmp(t, name)) - continue; - sns = sym->ns; - if (sns == ns) - return sym; - /* - * When a lookup is done in a namespace associated - * to a struct we also want symbols of NS_IDEN which - * are typedef, because in other case we cannot declare - * fields of such types. - * TODO: Remove this trick - */ - if (sns == NS_KEYWORD || - (sym->flags & STYPEDEF) && ns >= NS_STRUCTS) { - return sym; - } - } - return (alloc == ALLOC) ? newsym(ns, name) : NULL; -} - -Symbol * -install(int ns, Symbol *sym) -{ - if (sym->flags & SDECLARED || sym->ctx != curctx) { - if (sym->ctx == curctx && ns == sym->ns) - return NULL; - sym = newsym(ns, sym->name); - } - return linkhash(sym); -} - -void -keywords(struct keyword *key, int ns) -{ - Symbol *sym; - - for ( ; key->str; ++key) { - sym = linkhash(newsym(ns, key->str)); - sym->token = key->token; - sym->u.token = key->value; - } - /* - * Remove all the predefined symbols from * the symbol list. It - * will make faster some operations. There is no problem of memory - * leakeage because this memory is not ever freed - */ - counterid = 0; - head = NULL; -} - -void -builtins(struct builtin *built) -{ - Symbol *sym; - struct builtin *bp; - - for (bp = built; bp->str; ++bp) { - sym = linkhash(newsym(NS_KEYWORD, bp->str)); - sym->token = BUILTIN; - sym->u.fun = bp->fun; - } - /* - * Remove all the predefined symbols from * the symbol list. It - * will make faster some operations. There is no problem of memory - * leakeage because this memory is not ever freed - */ - counterid = 0; - head = NULL; -} diff --git a/cc1/target/amd64-sysv/arch.c b/cc1/target/amd64-sysv/arch.c @@ -1,220 +0,0 @@ -static char sccsid[] = "@(#) ./cc1/arch/amd64-sysv/arch.c"; - -#include "../../../inc/scc.h" -#include "../../cc1.h" - -#define RANK_BOOL 0 -#define RANK_SCHAR 1 -#define RANK_UCHAR 1 -#define RANK_CHAR 1 -#define RANK_SHORT 2 -#define RANK_USHORT 2 -#define RANK_INT 3 -#define RANK_UINT 3 -#define RANK_LONG 4 -#define RANK_ULONG 4 -#define RANK_LLONG 5 -#define RANK_ULLONG 5 -#define RANK_FLOAT 6 -#define RANK_DOUBLE 7 -#define RANK_LDOUBLE 8 - -/* - * Initializaion of type pointers were done with - * a C99 initilizator '... = &(Type) {...', but - * c compiler in Plan9 gives error with this - * syntax, so I have switched it to this ugly form - * I hope I will change it again in the future - */ - -static Type types[] = { - { /* 0 = voidtype */ - .op = VOID, - .letter = L_VOID, - }, - { /* 1 = pvoidtype */ - .op = PTR, - .letter = L_POINTER, - .prop = TDEFINED, - .type = &types[5], /* chartype */ - .size = 8, - .align = 8, - }, - { /* 2 = booltype */ - .op = INT, - .letter = L_BOOL, - .prop = TDEFINED | TINTEGER | TARITH, - .size = 1, - .align = 1, - .n.rank = RANK_BOOL, - }, - { /* 3 = schartype */ - .op = INT, - .letter = L_INT8, - .prop = TDEFINED | TINTEGER | TARITH | TSIGNED, - .size = 1, - .align = 1, - .n.rank = RANK_SCHAR, - }, - { /* 4 = uchartype */ - .op = INT, - .letter = L_UINT8, - .prop = TDEFINED | TINTEGER | TARITH, - .size = 1, - .align = 1, - .n.rank = RANK_UCHAR, - }, - { /* 5 = chartype */ - .op = INT, - .letter = L_INT8, - .prop = TDEFINED | TINTEGER | TARITH | TSIGNED, - .size = 1, - .align = 1, - .n.rank = RANK_CHAR, - }, - { /* 6 = ushortype */ - .op = INT, - .letter = L_UINT16, - .prop = TDEFINED | TINTEGER | TARITH, - .size = 2, - .align = 2, - .n.rank = RANK_USHORT, - }, - { /* 7 = shortype */ - .op = INT, - .letter = L_INT16, - .prop = TDEFINED | TINTEGER | TARITH | TSIGNED, - .size = 2, - .align = 2, - .n.rank = RANK_SHORT, - }, - { /* 8 = uinttype */ - .op = INT, - .letter = L_UINT32, - .prop = TDEFINED | TINTEGER | TARITH, - .size = 4, - .align = 4, - .n.rank = RANK_UINT, - }, - { /* 9 = inttype */ - .op = INT, - .letter = L_INT32, - .prop = TDEFINED | TINTEGER | TARITH | TSIGNED, - .size = 4, - .align = 4, - .n.rank = RANK_INT, - }, - { /* 10 = longtype */ - .op = INT, - .letter = L_INT64, - .prop = TDEFINED | TINTEGER | TARITH | TSIGNED, - .size = 8, - .align = 8, - .n.rank = RANK_LONG, - }, - { /* 11 = ulongtype */ - .op = INT, - .letter = L_UINT64, - .prop = TDEFINED | TINTEGER | TARITH, - .size = 8, - .align = 8, - .n.rank = RANK_ULONG, - }, - { /* 12 = ullongtype */ - .op = INT, - .letter = L_UINT64, - .prop = TDEFINED | TINTEGER | TARITH, - .size = 8, - .align = 8, - .n.rank = RANK_ULLONG, - }, - { /* 13 = llongtype */ - .op = INT, - .letter = L_INT64, - .prop = TDEFINED | TINTEGER | TARITH | TSIGNED, - .size = 8, - .align = 8, - .n.rank = RANK_LLONG, - }, - { /* 14 = floattype */ - .op = FLOAT, - .letter = L_FLOAT, - .prop = TDEFINED | TARITH, - .size = 4, - .align = 4, - .n.rank = RANK_FLOAT, - }, - { /* 15 = doubletype */ - .op = FLOAT, - .letter = L_DOUBLE, - .prop = TDEFINED | TARITH, - .size = 8, - .align = 8, - .n.rank = RANK_DOUBLE, - }, - { /* 16 = ldoubletype */ - .op = FLOAT, - .letter = L_LDOUBLE, - .prop = TDEFINED | TARITH, - .size = 16, - .align = 16, - .n.rank = RANK_LDOUBLE, - }, - { /* 17 = sizettype */ - .op = INT, - .letter = L_UINT64, - .prop = TDEFINED | TINTEGER | TARITH, - .size = 8, - .align = 8, - .n.rank = RANK_UINT, - }, - { /* 18 = ellipsis */ - .op = ELLIPSIS, - .letter = L_ELLIPSIS, - .prop = TDEFINED, - }, - { /* 19 = pdifftype */ - .op = INT, - .letter = L_INT64, - .prop = TDEFINED | TINTEGER | TARITH | TSIGNED, - .size = 8, - .align = 8, - .n.rank = RANK_LONG, - }, - { /* 20 = va_type */ - .op = STRUCT, - .letter = L_VA_ARG, - .prop = TDEFINED, - .size = 24, - .align = 8, - }, -}; - -Type *voidtype = &types[0], *pvoidtype = &types[1], - *booltype = &types[2], *schartype = &types[3], - *uchartype = &types[4], *chartype = &types[5], - *ushortype = &types[6], *shortype = &types[7], - *uinttype = &types[8], *inttype = &types[9], - *longtype = &types[10], *ulongtype = &types[11], - *ullongtype = &types[12], *llongtype = &types[13], - *floattype = &types[14], *doubletype = &types[15], - *ldoubletype = &types[16], - *sizettype = &types[17], *pdifftype = &types[19], - *ellipsistype = &types[18], *va_type = &types[20], - *va_list_type; - -static Symbol dummy0 = {.u.i = 0, .type = &types[9]}, - dummy1 = {.u.i = 1, .type = &types[9]}; -Symbol *zero = &dummy0, *one = &dummy1; - -void -iarch(void) -{ - va_list_type = mktype(va_type, ARY, 1, NULL); -} - -int -valid_va_list(Type *tp) -{ - return tp->op == PTR && eqtype(tp->type, va_type, 1); -} diff --git a/cc1/target/amd64-sysv/arch.mk b/cc1/target/amd64-sysv/arch.mk @@ -1,5 +0,0 @@ - -OBJ-amd64-sysv= $(OBJ) target/amd64-sysv/arch.o - -$(LIBEXEC)/cc1-amd64-sysv: $(OBJ-amd64-sysv) - $(CC) $(SCC_LDFLAGS) $(OBJ-amd64-sysv) -lscc -o $@ diff --git a/cc1/target/arm64-sysv/arch.c b/cc1/target/arm64-sysv/arch.c @@ -1,220 +0,0 @@ -static char sccsid[] = "@(#) ./cc1/arch/arm64-sysv/arch.c"; - -#include "../../../inc/scc.h" -#include "../../cc1.h" - -#define RANK_BOOL 0 -#define RANK_SCHAR 1 -#define RANK_UCHAR 1 -#define RANK_CHAR 1 -#define RANK_SHORT 2 -#define RANK_USHORT 2 -#define RANK_INT 3 -#define RANK_UINT 3 -#define RANK_LONG 4 -#define RANK_ULONG 4 -#define RANK_LLONG 5 -#define RANK_ULLONG 5 -#define RANK_FLOAT 6 -#define RANK_DOUBLE 7 -#define RANK_LDOUBLE 8 - -/* - * Initializaion of type pointers were done with - * a C99 initilizator '... = &(Type) {...', but - * c compiler in Plan9 gives error with this - * syntax, so I have switched it to this ugly form - * I hope I will change it again in the future - */ - -static Type types[] = { - { /* 0 = voidtype */ - .op = VOID, - .letter = L_VOID, - }, - { /* 1 = pvoidtype */ - .op = PTR, - .letter = L_POINTER, - .prop = TDEFINED, - .type = &types[5], /* chartype */ - .size = 8, - .align = 8, - }, - { /* 2 = booltype */ - .op = INT, - .letter = L_BOOL, - .prop = TDEFINED | TINTEGER | TARITH, - .size = 1, - .align = 1, - .n.rank = RANK_BOOL, - }, - { /* 3 = schartype */ - .op = INT, - .letter = L_INT8, - .prop = TDEFINED | TINTEGER | TARITH | TSIGNED, - .size = 1, - .align = 1, - .n.rank = RANK_SCHAR, - }, - { /* 4 = uchartype */ - .op = INT, - .letter = L_UINT8, - .prop = TDEFINED | TINTEGER | TARITH, - .size = 1, - .align = 1, - .n.rank = RANK_UCHAR, - }, - { /* 5 = chartype */ - .op = INT, - .letter = L_INT8, - .prop = TDEFINED | TINTEGER | TARITH | TSIGNED, - .size = 1, - .align = 1, - .n.rank = RANK_CHAR, - }, - { /* 6 = ushortype */ - .op = INT, - .letter = L_UINT16, - .prop = TDEFINED | TINTEGER | TARITH, - .size = 2, - .align = 2, - .n.rank = RANK_USHORT, - }, - { /* 7 = shortype */ - .op = INT, - .letter = L_INT16, - .prop = TDEFINED | TINTEGER | TARITH | TSIGNED, - .size = 2, - .align = 2, - .n.rank = RANK_SHORT, - }, - { /* 8 = uinttype */ - .op = INT, - .letter = L_UINT32, - .prop = TDEFINED | TINTEGER | TARITH, - .size = 4, - .align = 4, - .n.rank = RANK_UINT, - }, - { /* 9 = inttype */ - .op = INT, - .letter = L_INT32, - .prop = TDEFINED | TINTEGER | TARITH | TSIGNED, - .size = 4, - .align = 4, - .n.rank = RANK_INT, - }, - { /* 10 = longtype */ - .op = INT, - .letter = L_INT64, - .prop = TDEFINED | TINTEGER | TARITH | TSIGNED, - .size = 8, - .align = 8, - .n.rank = RANK_LONG, - }, - { /* 11 = ulongtype */ - .op = INT, - .letter = L_UINT64, - .prop = TDEFINED | TINTEGER | TARITH, - .size = 8, - .align = 8, - .n.rank = RANK_ULONG, - }, - { /* 12 = ullongtype */ - .op = INT, - .letter = L_UINT64, - .prop = TDEFINED | TINTEGER | TARITH, - .size = 8, - .align = 8, - .n.rank = RANK_ULLONG, - }, - { /* 13 = llongtype */ - .op = INT, - .letter = L_INT64, - .prop = TDEFINED | TINTEGER | TARITH | TSIGNED, - .size = 8, - .align = 8, - .n.rank = RANK_LLONG, - }, - { /* 14 = floattype */ - .op = FLOAT, - .letter = L_FLOAT, - .prop = TDEFINED | TARITH, - .size = 4, - .align = 4, - .n.rank = RANK_FLOAT, - }, - { /* 15 = doubletype */ - .op = FLOAT, - .letter = L_DOUBLE, - .prop = TDEFINED | TARITH, - .size = 8, - .align = 8, - .n.rank = RANK_DOUBLE, - }, - { /* 16 = ldoubletype */ - .op = FLOAT, - .letter = L_LDOUBLE, - .prop = TDEFINED | TARITH, - .size = 16, - .align = 16, - .n.rank = RANK_LDOUBLE, - }, - { /* 17 = sizettype */ - .op = INT, - .letter = L_UINT64, - .prop = TDEFINED | TINTEGER | TARITH, - .size = 8, - .align = 8, - .n.rank = RANK_UINT, - }, - { /* 18 = ellipsis */ - .op = ELLIPSIS, - .letter = L_ELLIPSIS, - .prop = TDEFINED, - }, - { /* 19 = pdifftype */ - .op = INT, - .letter = L_INT64, - .prop = TDEFINED | TINTEGER | TARITH | TSIGNED, - .size = 8, - .align = 8, - .n.rank = RANK_LONG, - }, - { /* 20 = va_type */ - .op = STRUCT, - .letter = L_VA_ARG, - .prop = TDEFINED, - .size = 24, - .align = 8, - }, -}; - -Type *voidtype = &types[0], *pvoidtype = &types[1], - *booltype = &types[2], *schartype = &types[3], - *uchartype = &types[4], *chartype = &types[5], - *ushortype = &types[6], *shortype = &types[7], - *uinttype = &types[8], *inttype = &types[9], - *longtype = &types[10], *ulongtype = &types[11], - *ullongtype = &types[12], *llongtype = &types[13], - *floattype = &types[14], *doubletype = &types[15], - *ldoubletype = &types[16], - *sizettype = &types[17], *pdifftype = &types[19], - *ellipsistype = &types[18], *va_type = &types[20], - *va_list_type; - -static Symbol dummy0 = {.u.i = 0, .type = &types[9]}, - dummy1 = {.u.i = 1, .type = &types[9]}; -Symbol *zero = &dummy0, *one = &dummy1; - -void -iarch(void) -{ - va_list_type = mktype(va_type, ARY, 1, NULL); -} - -int -valid_va_list(Type *tp) -{ - return tp->op == PTR && eqtype(tp->type, va_type, 1); -} diff --git a/cc1/target/arm64-sysv/arch.mk b/cc1/target/arm64-sysv/arch.mk @@ -1,5 +0,0 @@ - -OBJ-arm64-sysv= $(OBJ) target/arm64-sysv/arch.o - -$(LIBEXEC)/cc1-arm64-sysv: $(OBJ-arm64-sysv) - $(CC) $(SCC_LDFLAGS) $(OBJ-arm64-sysv) -lscc -o $@ diff --git a/cc1/target/i386-sysv/arch.c b/cc1/target/i386-sysv/arch.c @@ -1,221 +0,0 @@ -static char sccsid[] = "@(#) ./cc1/arch/i386-sysv/arch.c"; - -#include "../../../inc/scc.h" -#include "../../cc1.h" - -#define RANK_BOOL 0 -#define RANK_SCHAR 1 -#define RANK_UCHAR 1 -#define RANK_CHAR 1 -#define RANK_SHORT 2 -#define RANK_USHORT 2 -#define RANK_INT 3 -#define RANK_UINT 3 -#define RANK_LONG 4 -#define RANK_ULONG 4 -#define RANK_LLONG 5 -#define RANK_ULLONG 5 -#define RANK_FLOAT 6 -#define RANK_DOUBLE 7 -#define RANK_LDOUBLE 8 - -/* - * Initializaion of type pointers were done with - * a C99 initilizator '... = &(Type) {...', but - * c compiler in Plan9 gives error with this - * syntax, so I have switched it to this ugly form - * I hope I will change it again in the future - */ - -static Type types[] = { - { /* 0 = voidtype */ - .op = VOID, - .letter = L_VOID, - }, - { /* 1 = pvoidtype */ - .op = PTR, - .letter = L_POINTER, - .prop = TDEFINED, - .type = &types[5], /* chartype */ - .size = 4, - .align = 4, - }, - { /* 2 = booltype */ - .op = INT, - .letter = L_BOOL, - .prop = TDEFINED | TINTEGER | TARITH, - .size = 1, - .align = 1, - .n.rank = RANK_BOOL, - }, - { /* 3 = schartype */ - .op = INT, - .letter = L_INT8, - .prop = TDEFINED | TINTEGER | TARITH | TSIGNED, - .size = 1, - .align = 1, - .n.rank = RANK_SCHAR, - }, - { /* 4 = uchartype */ - .op = INT, - .letter = L_UINT8, - .prop = TDEFINED | TINTEGER | TARITH, - .size = 1, - .align = 1, - .n.rank = RANK_UCHAR, - }, - { /* 5 = chartype */ - .op = INT, - .letter = L_INT8, - .prop = TDEFINED | TINTEGER | TARITH | TSIGNED, - .size = 1, - .align = 1, - .n.rank = RANK_CHAR, - }, - { /* 6 = ushortype */ - .op = INT, - .letter = L_UINT16, - .prop = TDEFINED | TINTEGER | TARITH, - .size = 2, - .align = 2, - .n.rank = RANK_USHORT, - }, - { /* 7 = shortype */ - .op = INT, - .letter = L_INT16, - .prop = TDEFINED | TINTEGER | TARITH | TSIGNED, - .size = 2, - .align = 2, - .n.rank = RANK_SHORT, - }, - { /* 8 = uinttype */ - .op = INT, - .letter = L_UINT32, - .prop = TDEFINED | TINTEGER | TARITH, - .size = 4, - .align = 4, - .n.rank = RANK_UINT, - }, - { /* 9 = inttype */ - .op = INT, - .letter = L_INT32, - .prop = TDEFINED | TINTEGER | TARITH | TSIGNED, - .size = 4, - .align = 4, - .n.rank = RANK_INT, - }, - { /* 10 = longtype */ - .op = INT, - .letter = L_INT32, - .prop = TDEFINED | TINTEGER | TARITH | TSIGNED, - .size = 4, - .align = 4, - .n.rank = RANK_LONG, - }, - { /* 11 = ulongtype */ - .op = INT, - .letter = L_UINT32, - .prop = TDEFINED | TINTEGER | TARITH, - .size = 4, - .align = 4, - .n.rank = RANK_ULONG, - }, - { /* 12 = ullongtype */ - .op = INT, - .letter = L_UINT64, - .prop = TDEFINED | TINTEGER | TARITH, - .size = 8, - .align = 4, - .n.rank = RANK_ULLONG, - }, - { /* 13 = llongtype */ - .op = INT, - .letter = L_INT64, - .prop = TDEFINED | TINTEGER | TARITH | TSIGNED, - .size = 8, - .align = 4, - .n.rank = RANK_LLONG, - }, - { /* 14 = floattype */ - .op = FLOAT, - .letter = L_FLOAT, - .prop = TDEFINED | TARITH, - .size = 4, - .align = 4, - .n.rank = RANK_FLOAT, - }, - { /* 15 = doubletype */ - .op = FLOAT, - .letter = L_DOUBLE, - .prop = TDEFINED | TARITH, - .size = 8, - .align = 4, - .n.rank = RANK_DOUBLE, - }, - { /* 16 = ldoubletype */ - .op = FLOAT, - .letter = L_LDOUBLE, - .prop = TDEFINED | TARITH, - .size = 12, - .align = 4, - .n.rank = RANK_LDOUBLE, - }, - { /* 17 = sizettype */ - .op = INT, - .letter = L_UINT32, - .prop = TDEFINED | TINTEGER | TARITH, - .size = 4, - .align = 4, - .n.rank = RANK_UINT, - }, - { /* 18 = ellipsis */ - .op = ELLIPSIS, - .letter = L_ELLIPSIS, - .prop = TDEFINED, - }, - { /* 19 = pdifftype */ - .op = INT, - .letter = L_INT32, - .prop = TDEFINED | TINTEGER | TARITH | TSIGNED, - .size = 4, - .align = 4, - .n.rank = RANK_INT, - }, - { /* 20 = va_list_type */ - .op = PTR, - .letter = L_POINTER, - .prop = TDEFINED, - .size = 4, - .align = 4, - }, -}; - - -Type *voidtype = &types[0], *pvoidtype = &types[1], - *booltype = &types[2], *schartype = &types[3], - *uchartype = &types[4], *chartype = &types[5], - *ushortype = &types[6], *shortype = &types[7], - *uinttype = &types[8], *inttype = &types[9], - *longtype = &types[10], *ulongtype = &types[11], - *ullongtype = &types[12], *llongtype = &types[13], - *floattype = &types[14], *doubletype = &types[15], - *ldoubletype = &types[16], - *sizettype = &types[17], *pdifftype = &types[19], - *ellipsistype = &types[18], *va_list_type = &types[20]; - - - -static Symbol dummy0 = {.u.i = 0, .type = &types[9]}, - dummy1 = {.u.i = 1, .type = &types[9]}; -Symbol *zero = &dummy0, *one = &dummy1; - -void -iarch(void) -{ -} - -int -valid_va_list(Type *tp) -{ - return eqtype(tp, va_list_type, 1); -} diff --git a/cc1/target/i386-sysv/arch.mk b/cc1/target/i386-sysv/arch.mk @@ -1,5 +0,0 @@ - -OBJ-i386-sysv= $(OBJ) target/i386-sysv/arch.o - -$(LIBEXEC)/cc1-i386-sysv: $(OBJ-i386-sysv) - $(CC) $(SCC_LDFLAGS) $(OBJ-i386-sysv) -lscc -o $@ diff --git a/cc1/target/z80-scc/arch.c b/cc1/target/z80-scc/arch.c @@ -1,219 +0,0 @@ -static char sccsid[] = "@(#) ./cc1/arch/z80/arch.c"; - -#include "../../../inc/scc.h" -#include "../../cc1.h" - -#define RANK_BOOL 0 -#define RANK_SCHAR 1 -#define RANK_UCHAR 1 -#define RANK_CHAR 1 -#define RANK_SHORT 2 -#define RANK_USHORT 2 -#define RANK_INT 3 -#define RANK_UINT 3 -#define RANK_LONG 4 -#define RANK_ULONG 4 -#define RANK_LLONG 5 -#define RANK_ULLONG 5 -#define RANK_FLOAT 6 -#define RANK_DOUBLE 7 -#define RANK_LDOUBLE 8 - -/* - * Initializaion of type pointers were done with - * a C99 initilizator '... = &(Type) {...', but - * c compiler in Plan9 gives error with this - * syntax, so I have switched it to this ugly form - * I hope I will change it again in the future - */ - -static Type types[] = { - { /* 0 = voidtype */ - .op = VOID, - .letter = L_VOID, - }, - { /* 1 = pvoidtype */ - .op = PTR, - .letter = L_POINTER, - .prop = TDEFINED, - .type = &types[5], /* char type */ - .size = 2, - .align = 2, - }, - { /* 2 = booltype */ - .op = INT, - .letter = L_BOOL, - .prop = TDEFINED | TINTEGER | TARITH, - .size = 1, - .align = 1, - .n.rank = RANK_BOOL, - }, - { /* 3 = schartype */ - .op = INT, - .letter = L_INT8, - .prop = TDEFINED | TINTEGER | TARITH | TSIGNED, - .size = 1, - .align = 1, - .n.rank = RANK_SCHAR, - }, - { /* 4 = uchartype */ - .op = INT, - .letter = L_UINT8, - .prop = TDEFINED | TINTEGER | TARITH, - .size = 1, - .align = 1, - .n.rank = RANK_UCHAR, - }, - { /* 5 = chartype */ - .op = INT, - .letter = L_UINT8, - .prop = TDEFINED | TINTEGER | TARITH | TSIGNED, - .size = 1, - .align = 1, - .n.rank = RANK_CHAR, - }, - { /* 6 = ushortype */ - .op = INT, - .letter = L_UINT16, - .prop = TDEFINED | TINTEGER | TARITH, - .size = 2, - .align = 1, - .n.rank = RANK_USHORT, - }, - { /* 7 = shortype */ - .op = INT, - .letter = L_INT16, - .prop = TDEFINED | TINTEGER | TARITH | TSIGNED, - .size = 2, - .align = 1, - .n.rank = RANK_SHORT, - }, - { /* 8 = uinttype */ - .op = INT, - .letter = L_UINT16, - .prop = TDEFINED | TINTEGER | TARITH, - .size = 2, - .align = 1, - .n.rank = RANK_UINT, - }, - { /* 9 = inttype */ - .op = INT, - .letter = L_INT16, - .prop = TDEFINED | TINTEGER | TARITH | TSIGNED, - .size = 2, - .align = 1, - .n.rank = RANK_INT, - }, - { /* 10 = longtype */ - .op = INT, - .letter = L_INT32, - .prop = TDEFINED | TINTEGER | TARITH | TSIGNED, - .size = 4, - .align = 1, - .n.rank = RANK_LONG, - }, - { /* 11 = ulongtype */ - .op = INT, - .letter = L_UINT32, - .prop = TDEFINED | TINTEGER | TARITH, - .size = 4, - .align = 1, - .n.rank = RANK_ULONG, - }, - { /* 12 = ullongtype */ - .op = INT, - .letter = L_UINT64, - .prop = TDEFINED | TINTEGER | TARITH, - .size = 8, - .align = 1, - .n.rank = RANK_ULLONG, - }, - { /* 13 = llongtype */ - .op = INT, - .letter = L_INT64, - .prop = TDEFINED | TINTEGER | TARITH | TSIGNED, - .size = 8, - .align = 1, - .n.rank = RANK_LLONG, - }, - { /* 14 = floattype */ - .op = FLOAT, - .letter = L_FLOAT, - .prop = TDEFINED | TARITH, - .size = 4, - .align = 1, - .n.rank = RANK_FLOAT, - }, - { /* 15 = doubletype */ - .op = FLOAT, - .letter = L_DOUBLE, - .prop = TDEFINED | TARITH, - .size = 8, - .align = 1, - .n.rank = RANK_DOUBLE, - }, - { /* 16 = ldoubletype */ - .op = FLOAT, - .letter = L_LDOUBLE, - .prop = TDEFINED | TARITH, - .size = 16, - .align = 1, - .n.rank = RANK_LDOUBLE, - }, - { /* 17 = sizettype */ - .op = INT, - .letter = L_UINT16, - .prop = TDEFINED | TINTEGER | TARITH, - .size = 2, - .align = 1, - .n.rank = RANK_UINT, - }, - { /* 18 = ellipsis */ - .op = ELLIPSIS, - .letter = L_ELLIPSIS, - .prop = TDEFINED, - }, - { /* 7 = pdifftype */ - .op = INT, - .letter = L_INT16, - .prop = TDEFINED | TINTEGER | TARITH | TSIGNED, - .size = 2, - .align = 1, - .n.rank = RANK_SHORT, - }, - { /* 20 = va_list_type */ - .op = PTR, - .letter = L_POINTER, - .prop = TDEFINED, - .size = 2, - .align = 1, - } -}; - -Type *voidtype = &types[0], *pvoidtype = &types[1], - *booltype = &types[2], *schartype = &types[3], - *uchartype = &types[4], *chartype = &types[5], - *ushortype = &types[6], *shortype = &types[7], - *uinttype = &types[8], *inttype = &types[9], - *longtype = &types[10], *ulongtype = &types[11], - *ullongtype = &types[12], *llongtype = &types[13], - *floattype = &types[14], *doubletype = &types[15], - *ldoubletype = &types[16], - *sizettype = &types[17], *pdifftype = &types[19], - *ellipsistype = &types[18], *va_list_type = &types[20]; - - -static Symbol dummy0 = {.u.i = 0, .type = &types[9]}, - dummy1 = {.u.i = 1, .type = &types[9]}; -Symbol *zero = &dummy0, *one = &dummy1; - -void -iarch(void) -{ -} - -int -valid_va_list(Type *tp) -{ - return eqtype(tp, va_list_type, 1); -} diff --git a/cc1/target/z80-scc/arch.mk b/cc1/target/z80-scc/arch.mk @@ -1,5 +0,0 @@ - -OBJ-z80-scc= $(OBJ) target/z80-scc/arch.o - -$(LIBEXEC)/cc1-z80-scc: $(OBJ-z80-scc) - $(CC) $(SCC_LDFLAGS) $(OBJ-z80-scc) -lscc -o $@ diff --git a/cc1/types.c b/cc1/types.c @@ -1,438 +0,0 @@ -static char sccsid[] = "@(#) ./cc1/types.c"; -#include <assert.h> -#include <inttypes.h> -#include <stdlib.h> -#include <string.h> - -#include <cstd.h> -#include "../inc/scc.h" -#include "cc1.h" - -#define NR_TYPE_HASH 16 -#define HASH(t) (((t)->op ^ (uintptr_t) (t)->type>>3) & NR_TYPE_HASH-1) - -static Type *typetab[NR_TYPE_HASH], *localtypes; - -/* FIXME: - * Compiler can generate warnings here if the ranges of TINT, - * TUINT and TFLOAT are smaller than any of the constants in this - * array. Ignore them if you know that the target types are correct - */ -static struct limits limits[][4] = { - { - { /* 0 = unsigned 1 byte */ - .min.i = 0, - .max.i = 0xff - }, - { /* 1 = unsigned 2 bytes */ - .min.i = 0, - .max.i = 0xffff - }, - { /* 2 = unsigned 4 bytes */ - .min.i = 0, - .max.i = 0xffffffff - }, - { /* 3 = unsigned 8 bytes */ - .min.i = 0, - .max.i = 0xffffffffffffffff - } - }, - { - { /* 0 = signed 1 byte */ - .min.i = -0x7f-1, - .max.i = 0x7f - }, - { /* 1 = signed 2 byte */ - .min.i = -0x7fff-1, - .max.i = 0x7fff - }, - { /* 2 = signed 4 byte */ - .min.i = -0x7fffffff-1, - .max.i = 0x7fffffff - }, - { /* 3 = signed 8 byte */ - .min.i = -0x7fffffffffffffff-1, - .max.i = 0x7fffffffffffffff, - } - }, - { - { - /* 0 = float 4 bytes */ - .min.f = -1, - .max.f = 2 - }, - { - /* 1 = float 8 bytes */ - .min.f = -1, - .max.f = 2, - }, - { - /* 2 = float 16 bytes */ - .min.f = -1, - .max.f = 2, - } - } -}; - -struct limits * -getlimits(Type *tp) -{ - int ntable, ntype; - - switch (tp->op) { - case ENUM: - case INT: - ntable = ((tp->prop & TSIGNED) != 0); - switch (tp->size) { - case 1: ntype = 0; break; - case 2: ntype = 1; break; - case 4: ntype = 2; break; - case 8: ntype = 3; break; - } - break; - case FLOAT: - ntable = 2; - switch (tp->size) { - case 4: ntype = 0; break; - case 8: ntype = 1; break; - case 16: ntype = 2; break; - } - break; - default: - abort(); - } - - return &limits[ntable][ntype]; -} - -Type * -ctype(int type, int sign, int size) -{ - switch (type) { - case CHAR: - if (size) - goto invalid_type; - switch (sign) { - case 0: - return chartype; - case SIGNED: - return schartype; - case UNSIGNED: - return uchartype; - } - break; - case VA_LIST: - if (size || sign) - goto invalid_type; - return va_list_type; - case VOID: - if (size || sign) - goto invalid_type; - return voidtype; - case BOOL: - if (size || sign) - goto invalid_type; - return booltype; - case 0: - case INT: - switch (size) { - case 0: - return (sign == UNSIGNED) ? uinttype : inttype; - case SHORT: - return (sign == UNSIGNED) ? ushortype : shortype; - case LONG: - return (sign == UNSIGNED) ? ulongtype : longtype; - case LLONG: - return (sign == UNSIGNED) ? ullongtype : llongtype; - } - break; - case DOUBLE: - if (size == LLONG) - goto invalid_type; - if (size == LONG) - size = LLONG; - else - size = LONG; - goto floating; - case FLOAT: - if (size == LLONG) - goto invalid_type; - floating: - if (sign) - goto invalid_type; - switch (size) { - case 0: - return floattype; - case LONG: - return doubletype; - case LLONG: - return ldoubletype; - } - break; - } - -invalid_type: - error("invalid type specification"); -} - -void -typesize(Type *tp) -{ - Symbol **sp; - Type *type; - unsigned long size, offset; - int align, a; - TINT n; - - switch (tp->op) { - case ARY: - /* FIXME: Control overflow */ - tp->size = tp->n.elem * tp->type->size; - tp->align = tp->type->align; - return; - case PTR: - tp->size = pvoidtype->size; - tp->align = pvoidtype->align; - return; - case STRUCT: - case UNION: - /* FIXME: Control overflow */ - /* - * The alignment of the struct/union is - * he alignment of the largest included type. - * The size of an union is the size of the largest - * field, and the size of a struct is the sum - * of the size of every field plus padding bits. - */ - offset = align = size = 0; - n = tp->n.elem; - for (sp = tp->p.fields; n--; ++sp) { - (*sp)->u.i = offset; - type = (*sp)->type; - a = type->align; - if (a > align) - align = a; - if (tp->op == STRUCT) { - if (--a != 0) - size = (size + a) & ~a; - size += type->size; - offset = size; - } else { - if (type->size > size) - size = type->size; - } - } - - tp->align = align; - /* - * We have to add the padding bits to - * ensure next struct in an array is well - * alignment. - */ - if (tp->op == STRUCT && align-- > 1) - size += size+align & ~align; - tp->size = size; - return; - case ENUM: - tp->size = inttype->size; - tp->align = inttype->align; - return; - case FTN: - return; - default: - abort(); - } -} - -Type * -deftype(Type *tp) -{ - tp->prop |= TDEFINED; - typesize(tp); - emit(OTYP, tp); - return tp; -} - -static Type * -newtype(Type *base) -{ - Type *tp; - size_t siz; - - tp = xmalloc(sizeof(*tp)); - *tp = *base; - tp->id = newid(); - - if (tp->op == FTN) { - siz = tp->n.elem * sizeof(Type *); - tp->p.pars = memcpy(xmalloc(siz), tp->p.pars, siz); - } - - if (curfun) { - /* it is a type defined in the body of a function */ - tp->next = localtypes; - localtypes = tp; - } - if (tp->prop & TDEFINED) - deftype(tp); - return tp; -} - -Type * -mktype(Type *tp, int op, TINT nelem, Type *pars[]) -{ - Type **tbl, type; - Type *bp; - - if (op == PTR && tp == voidtype) - return pvoidtype; - - memset(&type, 0, sizeof(type)); - type.type = tp; - type.op = op; - type.p.pars = pars; - type.n.elem = nelem; - - switch (op) { - case ARY: - if (tp == voidtype) { - errorp("declaration of array of voids type"); - tp = inttype; - } - type.letter = L_ARRAY; - if (nelem != 0) - type.prop |= TDEFINED; - break; - case KRFTN: - type.prop |= TDEFINED | TK_R; - type.op = FTN; - type.letter = L_FUNCTION; - break; - case FTN: - if (nelem > 0 && pars[nelem-1] == ellipsistype) - type.prop |= TELLIPSIS; - type.letter = L_FUNCTION; - type.prop |= TDEFINED; - break; - case PTR: - type.letter = L_POINTER; - type.prop |= TDEFINED; - break; - case ENUM: - type.letter = inttype->letter; - type.prop |= TINTEGER | TARITH; - type.n.rank = inttype->n.rank; - goto create_type; - case STRUCT: - type.letter = L_STRUCT; - type.prop |= TAGGREG; - goto create_type; - case UNION: - type.letter = L_UNION; - type.prop |= TAGGREG; - create_type: - return newtype(&type); - default: - abort(); - } - - tbl = &typetab[HASH(&type)]; - for (bp = *tbl; bp; bp = bp->h_next) { - if (eqtype(bp, &type, 0)) - return bp; - } - - bp = newtype(&type); - bp->h_next = *tbl; - *tbl = bp; - - return bp; -} - -int -eqtype(Type *tp1, Type *tp2, int equiv) -{ - TINT n; - Type **p1, **p2; - Symbol **s1, **s2; - - if (tp1 == tp2) - return 1; - if (!tp1 || !tp2) - return 0; - if (tp1->op != tp2->op) - return 0; - - switch (tp1->op) { - case UNION: - case STRUCT: - if (tp1->letter != tp2->letter) - return 0; - if (tp1->tag->name || tp2->tag->name) - return tp1->tag == tp2->tag; - if (tp1->n.elem != tp2->n.elem) - return 0; - s1 = tp1->p.fields, s2 = tp2->p.fields; - for (n = tp1->n.elem; n > 0; --n, ++s1, ++s2) { - if (strcmp((*s1)->name, (*s2)->name)) - return 0; - if (!eqtype((*s1)->type, (*s2)->type, equiv)) - return 0; - } - return 1; - case FTN: - if (tp1->n.elem != tp2->n.elem) - return 0; - p1 = tp1->p.pars, p2 = tp2->p.pars; - for (n = tp1->n.elem; n > 0; --n) { - if (!eqtype(*p1++, *p2++, equiv)) - return 0; - } - goto check_base; - case ARY: - if (equiv && (tp1->n.elem == 0 || tp2->n.elem == 0)) - goto check_base; - if (tp1->n.elem != tp2->n.elem) - return 0; - case PTR: - check_base: - return eqtype(tp1->type, tp2->type, equiv); - case VOID: - case ENUM: - return 0; - case INT: - case FLOAT: - return tp1->letter == tp2->letter; - default: - abort(); - } -} - -void -flushtypes(void) -{ - Type *tp, *next, **h; - - for (tp = localtypes; tp; tp = next) { - next = tp->next; - switch (tp->op) { - default: - /* - * All the local types are linked after - * global types, and since we are - * unlinking them in the inverse order - * we do know that tp is always the head - * of the collision list - */ - h = &typetab[HASH(tp)]; - assert(*h == tp); - *h = tp->h_next; - case STRUCT: - case UNION: - case ENUM: - free(tp); - break; - } - } - localtypes = NULL; -} diff --git a/cc2/Makefile b/cc2/Makefile @@ -1,35 +0,0 @@ -.POSIX: - -PROJECTDIR = .. -include $(PROJECTDIR)/rules.mk -include $(LIBSCC)/libdep.mk - -MORECFLAGS = -I$(PROJECTDIR)/inc/$(STD) - -OBJ = main.o parser.o peep.o symbol.o node.o code.o optm.o - -TARGETS = $(LIBEXEC)/cc2-amd64-sysv $(LIBEXEC)/cc2-i386-sysv \ - $(LIBEXEC)/cc2-qbe_amd64-sysv $(LIBEXEC)/cc2-z80-scc - -all: $(TARGETS) - -$(TARGETS): $(LIBDIR)/libscc.a - -dep: - $(PROJECTDIR)/mkdep.sh - -error.h: cc2.h - rm -f $@; trap 'rm -f $$$$.h' EXIT INT QUIT ;\ - awk -f generror.awk cc2.h > $$$$.h && mv $$$$.h $@ - -clean: - rm -f *.o error.h - rm -f target/*/*.o - rm -f $(TARGETS) - -include target/amd64-sysv/target.mk -include target/i386-sysv/target.mk -include target/qbe_amd64-sysv/target.mk -include target/qbe_arm64-sysv/target.mk -include target/z80-scc/target.mk -include deps.mk diff --git a/cc2/code.c b/cc2/code.c @@ -1,133 +0,0 @@ -static char sccsid[] = "@(#) ./cc2/code.c"; -#include <stdlib.h> -#include <string.h> - -#include "../inc/scc.h" -#include "cc2.h" - -Inst *pc, *prog; - -static void -nextpc(void) -{ - Inst *new; - - new = xcalloc(1, sizeof(*new)); /* TODO: create an arena */ - - if (!pc) { - prog = new; - } else { - new->next = pc->next; - pc->next = new; - } - - /* SNONE being 0, calloc initialized {from1,from2,to}.kind for us */ - new->prev = pc; - pc = new; -} - -static void -addr(Node *np, Addr *addr) -{ - Symbol *sym; - - switch (np->op) { - case OREG: - /* TODO: - * At this moment this op is used also for register variables - */ - addr->kind = SREG; - addr->u.reg = np->u.reg; - break; - case OCONST: - addr->kind = SCONST; - /* TODO: Add support for more type of constants */ - addr->u.i = np->u.i; - break; - case OTMP: - case OLABEL: - case OAUTO: - case OMEM: - sym = np->u.sym; - addr->kind = sym->kind; - addr->u.sym = sym; - break; - default: - abort(); - } -} - -Symbol * -newlabel(void) -{ - Symbol *sym = getsym(TMPSYM); - - sym->kind = SLABEL; - return sym; -} - -Node * -label2node(Node *np, Symbol *sym) -{ - if(!sym) - sym = newlabel(); - if (!np) - np = node(OLABEL); - np->op = OLABEL; - np->u.sym = sym; - - return np; -} - -Node * -constnode(Node *np, TUINT n, Type *tp) -{ - if (!np) - np = node(OCONST); - np->op = OCONST; - np->left = NULL; - np->right = NULL; - np->type = *tp; - np->u.i = n; - return np; -} - -void -setlabel(Symbol *sym) -{ - if (!sym) - return; - code(0, NULL, NULL, NULL); - pc->label = sym; - sym->u.inst = pc; -} - -void -code(int op, Node *to, Node *from1, Node *from2) -{ - nextpc(); - if (from1) - addr(from1, &pc->from1); - if (from2) - addr(from2, &pc->from2); - if (to) - addr(to, &pc->to); - pc->op = op; -} - -void -delcode(void) -{ - Inst *prev = pc->prev, *next = pc->next; - - free(pc); - if (!prev) { - pc = next; - prog = NULL; - } else { - pc = prev; - prev->next = next; - if (next) - next->prev = prev; - } -} diff --git a/cc2/deps.mk b/cc2/deps.mk @@ -1,61 +0,0 @@ -parser.c: $(PROJECTDIR)/inc/$(STD)/cstd.h -target/amd64-sysv/code.o: $(INCLUDE)/$(STD)/cstd.h -target/i386-sysv/code.o: $(INCLUDE)/$(STD)/cstd.h -target/qbe/cgen.o: $(INCLUDE)/$(STD)/cstd.h -target/z80-scc/code.o: $(INCLUDE)/$(STD)/cstd.h - -#deps -code.o: ../inc/scc.h -code.o: cc2.h -main.o: ../inc/arg.h -main.o: ../inc/scc.h -main.o: cc2.h -main.o: error.h -node.o: ../inc/scc.h -node.o: cc2.h -optm.o: ../inc/scc.h -optm.o: cc2.h -parser.o: ../inc/scc.h -parser.o: cc2.h -peep.o: ../inc/scc.h -peep.o: cc2.h -symbol.o: ../inc/scc.h -symbol.o: cc2.h -target/amd64-sysv/cgen.o: target/amd64-sysv/../../../inc/scc.h -target/amd64-sysv/cgen.o: target/amd64-sysv/../../cc2.h -target/amd64-sysv/cgen.o: target/amd64-sysv/arch.h -target/amd64-sysv/code.o: target/amd64-sysv/../../../inc/scc.h -target/amd64-sysv/code.o: target/amd64-sysv/../../cc2.h -target/amd64-sysv/code.o: target/amd64-sysv/arch.h -target/amd64-sysv/optm.o: target/amd64-sysv/../../../inc/scc.h -target/amd64-sysv/optm.o: target/amd64-sysv/../../cc2.h -target/amd64-sysv/types.o: target/amd64-sysv/../../../inc/scc.h -target/amd64-sysv/types.o: target/amd64-sysv/../../cc2.h -target/i386-sysv/cgen.o: target/i386-sysv/../../../inc/scc.h -target/i386-sysv/cgen.o: target/i386-sysv/../../cc2.h -target/i386-sysv/cgen.o: target/i386-sysv/arch.h -target/i386-sysv/code.o: target/i386-sysv/../../../inc/scc.h -target/i386-sysv/code.o: target/i386-sysv/../../cc2.h -target/i386-sysv/code.o: target/i386-sysv/arch.h -target/i386-sysv/optm.o: target/i386-sysv/../../../inc/scc.h -target/i386-sysv/optm.o: target/i386-sysv/../../cc2.h -target/i386-sysv/types.o: target/i386-sysv/../../../inc/scc.h -target/i386-sysv/types.o: target/i386-sysv/../../cc2.h -target/qbe/cgen.o: target/qbe/../../../inc/scc.h -target/qbe/cgen.o: target/qbe/../../cc2.h -target/qbe/cgen.o: target/qbe/arch.h -target/qbe/code.o: target/qbe/../../../inc/scc.h -target/qbe/code.o: target/qbe/../../cc2.h -target/qbe/code.o: target/qbe/arch.h -target/qbe/optm.o: target/qbe/../../../inc/scc.h -target/qbe/optm.o: target/qbe/../../cc2.h -target/z80-scc/cgen.o: target/z80-scc/../../../inc/scc.h -target/z80-scc/cgen.o: target/z80-scc/../../cc2.h -target/z80-scc/cgen.o: target/z80-scc/arch.h -target/z80-scc/code.o: target/z80-scc/../../../inc/scc.h -target/z80-scc/code.o: target/z80-scc/../../cc2.h -target/z80-scc/code.o: target/z80-scc/arch.h -target/z80-scc/optm.o: target/z80-scc/../../../inc/scc.h -target/z80-scc/optm.o: target/z80-scc/../../cc2.h -target/z80-scc/types.o: target/z80-scc/../../../inc/scc.h -target/z80-scc/types.o: target/z80-scc/../../cc2.h diff --git a/cc2/main.c b/cc2/main.c @@ -1,70 +0,0 @@ -static char sccsid[] = "@(#) ./cc2/main.c"; - -#include <errno.h> -#include <stdarg.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "../inc/arg.h" -#include "../inc/scc.h" -#include "cc2.h" -#include "error.h" - -char *argv0; - -void -error(unsigned nerror, ...) -{ - va_list va; - va_start(va, nerror); - vfprintf(stderr, errlist[nerror], va); - va_end(va); - putc('\n', stderr); - exit(1); -} - -static int -moreinput(void) -{ - int c; - -repeat: - if (feof(stdin)) - return 0; - if ((c = getchar()) == '\n' || c == EOF) - goto repeat; - ungetc(c, stdin); - return 1; -} - -static void -usage(void) -{ - fputs("usage: cc2 [irfile]\n", stderr); - exit(1); -} - -int -main(int argc, char *argv[]) -{ - ARGBEGIN { - default: - usage(); - } ARGEND - - if (argv[0] && !freopen(argv[0], "r", stdin)) - die("cc2: %s: %s", argv[0], strerror(errno)); - - while (moreinput()) { - parse(); - apply(optm_ind); - apply(optm_dep); - apply(sethi); - apply(cgen); - getbblocks(); /* TODO: run apply over asm ins too */ - peephole(); - writeout(); - } - return 0; -} diff --git a/cc2/node.c b/cc2/node.c @@ -1,142 +0,0 @@ -static char sccsid[] = "@(#) ./cc2/node.c"; -#include <stdlib.h> -#include <string.h> - -#include "../inc/scc.h" - -#include "cc2.h" - -#define NNODES 32 - -Node *curstmt; -Symbol *curfun; - -static Alloc *arena; - - -Node * -node(int op) -{ - struct arena *ap; - Node *np; - - if (!arena) - arena = alloc(sizeof(Node), NNODES); - np = memset(new(arena), 0, sizeof(*np)); - np->op = op; - - return np; -} - -#ifndef NDEBUG -#include <stdio.h> - -static void -prnode(Node *np) -{ - if (np->left) - prnode(np->left); - if (np->right) - prnode(np->right); - fprintf(stderr, "\t%c%lu", np->op, np->type.size); -} - -void -prtree(Node *np) -{ - prnode(np); - putc('\n', stderr); -} - -void -prforest(char *msg) -{ - Node *np; - - if (!curfun) - return; - - fprintf(stderr, "%s {\n", msg); - for (np = curfun->u.stmt; np; np = np->next) - prtree(np); - fputs("}\n", stderr); -} -#endif - -Node * -addstmt(Node *np, int flag) -{ - if (curstmt) - np->next = curstmt->next; - np->prev = curstmt; - - if (!curfun->u.stmt) - curfun->u.stmt = np; - else - curstmt->next = np; - - if (flag == SETCUR) - curstmt = np; - - return np; -} - -Node * -delstmt(void) -{ - Node *next, *prev; - - next = curstmt->next; - prev = curstmt->prev; - if (next) - next->prev = prev; - if (prev) - prev->next = next; - else - curfun->u.stmt = next; - deltree(curstmt); - - return curstmt = next; -} - -Node * -nextstmt(void) -{ - return curstmt = curstmt->next; -} - -void -delnode(Node *np) -{ - delete(arena, np); -} - -void -deltree(Node *np) -{ - if (!np) - return; - deltree(np->left); - deltree(np->right); - delnode(np); -} - -void -cleannodes(void) -{ - if (arena) { - dealloc(arena); - arena = NULL; - } - curstmt = NULL; -} - -void -apply(Node *(*fun)(Node *)) -{ - if (!curfun) - return; - curstmt = curfun->u.stmt; - while (curstmt) - (*fun)(curstmt) ? nextstmt() : delstmt(); -} diff --git a/cc2/optm.c b/cc2/optm.c @@ -1,9 +0,0 @@ -#include "../inc/scc.h" -#include "cc2.h" - -Node * -optm_ind(Node *np) -{ - return np; -} - diff --git a/cc2/parser.c b/cc2/parser.c @@ -1,722 +0,0 @@ -static char sccsid[] = "@(#) ./cc2/parser.c"; -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include <cstd.h> -#include "../inc/scc.h" - -#include "cc2.h" - -#define STACKSIZ 50 - -extern Type int8type, int16type, int32type, int64type, - uint8type, uint16type, uint32type, uint64type, - float32type, float64type, float80type, - booltype, - ptrtype, - voidtype, - arg_type; - -Type funetype = { - .flags = FUNF | ELLIPS -}; - -Type funtype = { - .flags = FUNF -}; - -union tokenop { - void *arg; - unsigned op; -}; - -struct swtch { - int nr; - Node *first; - Node *last; -}; - -static struct swtch swtbl[NR_BLOCK], *swp = swtbl; -static Symbol *lastfun; - -typedef void parsefun(char *, union tokenop); -static parsefun type, symbol, getname, unary, binary, ternary, call, - constant, composed, binit, einit, - jump, oreturn, loop, assign, - ocase, bswitch, eswitch, builtin; - -typedef void evalfun(void); -static evalfun vardecl, beginfun, endfun, endpars, stmt, - array, aggregate, flddecl, labeldcl; - -static struct decoc { - void (*eval)(void); - void (*parse)(char *token, union tokenop); - union tokenop u; -} optbl[] = { /* eval parse args */ - ['A'] = { vardecl, symbol, .u.op = SAUTO<<8 | OAUTO}, - ['R'] = { vardecl, symbol, .u.op = SREG<<8 | OREG}, - ['G'] = { vardecl, symbol, .u.op = SGLOB<<8 | OMEM}, - ['X'] = { vardecl, symbol, .u.op = SEXTRN<<8 | OMEM}, - ['Y'] = { vardecl, symbol, .u.op = SPRIV<<8 | OMEM}, - ['T'] = { vardecl, symbol, .u.op = SLOCAL<<8 | OMEM}, - ['M'] = { flddecl, symbol, .u.op = SMEMB<<8 | OMEM}, - ['L'] = { labeldcl, symbol, .u.op = SLABEL<<8 | OLABEL}, - - ['C'] = { NULL, type, .u.arg = &int8type}, - ['I'] = { NULL, type, .u.arg = &int16type}, - ['W'] = { NULL, type, .u.arg = &int32type}, - ['Q'] = { NULL, type, .u.arg = &int64type}, - ['K'] = { NULL, type, .u.arg = &uint8type}, - ['N'] = { NULL, type, .u.arg = &uint16type}, - ['Z'] = { NULL, type, .u.arg = &uint32type}, - ['O'] = { NULL, type, .u.arg = &uint64type}, - ['J'] = { NULL, type, .u.arg = &float32type}, - ['D'] = { NULL, type, .u.arg = &float64type}, - ['H'] = { NULL, type, .u.arg = &float80type}, - ['0'] = { NULL, type, .u.arg = &voidtype}, - ['B'] = { NULL, type, .u.arg = &booltype}, - ['P'] = { NULL, type, .u.arg = &ptrtype}, - ['E'] = { NULL, type, .u.arg = &funetype}, - ['1'] = { NULL, type, .u.arg = &arg_type}, - - ['F'] = { NULL, type, .u.arg = &funtype}, - ['V'] = { array,composed, 0}, - ['U'] = {aggregate,composed, 0}, - ['S'] = {aggregate,composed, 0}, - - ['"'] = { NULL, getname, 0}, - ['{'] = { beginfun, NULL, 0}, - ['}'] = { endfun, NULL, 0}, - ['('] = { NULL, binit, 0}, - [')'] = { NULL, einit, 0}, - ['\\'] = { endpars, NULL, 0}, - ['\t'] = { stmt, NULL, 0}, - - ['~'] = { NULL, unary, .u.op = OCPL}, - ['_'] = { NULL, unary, .u.op = OSNEG}, - ['\''] = { NULL, unary, .u.op = OADDR}, - ['@'] = { NULL, unary, .u.op = OPTR}, - ['g'] = { NULL, unary, .u.op = OCAST}, - ['p'] = { NULL, unary, .u.op = OPAR}, - ['n'] = { NULL, unary, .u.op = ONEG}, - - ['a'] = { NULL, binary, .u.op = OAND}, - ['o'] = { NULL, binary, .u.op = OOR}, - ['.'] = { NULL, binary, .u.op = OFIELD}, - ['+'] = { NULL, binary, .u.op = OADD}, - ['-'] = { NULL, binary, .u.op = OSUB}, - ['*'] = { NULL, binary, .u.op = OMUL}, - ['%'] = { NULL, binary, .u.op = OMOD}, - ['/'] = { NULL, binary, .u.op = ODIV}, - ['l'] = { NULL, binary, .u.op = OSHL}, - ['r'] = { NULL, binary, .u.op = OSHR}, - ['<'] = { NULL, binary, .u.op = OLT}, - ['>'] = { NULL, binary, .u.op = OGT}, - ['['] = { NULL, binary, .u.op = OLE}, - [']'] = { NULL, binary, .u.op = OGE}, - ['='] = { NULL, binary, .u.op = OEQ}, - ['!'] = { NULL, binary, .u.op = ONE}, - ['&'] = { NULL, binary, .u.op = OBAND}, - ['|'] = { NULL, binary, .u.op = OBOR}, - ['^'] = { NULL, binary, .u.op = OBXOR}, - [','] = { NULL, binary, .u.op = OCOMMA}, - ['m'] = { NULL, builtin,.u.op = OBUILTIN}, - - [':'] = { NULL, assign, .u.op = OASSIG}, - ['?'] = { NULL, ternary, .u.op = OASK}, - ['c'] = { NULL, call, .u.op = OCALL}, - ['z'] = { NULL, call, .u.op = OCALLE}, - - ['#'] = { NULL,constant, .u.op = OCONST}, - - ['j'] = { NULL, jump, .u.op = OJMP}, - ['y'] = { NULL, jump, .u.op = OBRANCH}, - ['h'] = { NULL, oreturn, .u.op = ORET}, - ['i'] = { NULL, NULL, .u.op = OINC}, - ['d'] = { NULL, NULL, .u.op = ODEC}, - - ['b'] = { NULL, loop, .u.op = OBLOOP}, - ['e'] = { NULL, loop, .u.op = OELOOP}, - - ['v'] = { NULL, ocase, .u.op = OCASE}, - ['f'] = { NULL, ocase, .u.op = ODEFAULT}, - ['t'] = { NULL, eswitch, .u.op = OESWITCH}, - ['s'] = { NULL, bswitch, .u.op = OBSWITCH}, -}; - -static int sclass, inpars, ininit, endf, lineno; -static void *stack[STACKSIZ], **sp = stack; - -static Node * -push(void *elem) -{ - if (sp == &stack[STACKSIZ]) - error(ESTACKO); - return *sp++ = elem; -} - -static void * -pop(void) -{ - if (sp == stack) - error(ESTACKU); - return *--sp; -} - -static int -empty(void) -{ - return sp == stack; -} - -static void -type(char *token, union tokenop u) -{ - push(u.arg); -} - -static void -composed(char *token, union tokenop u) -{ - Symbol *sym; - - sym = getsym(atoi(token+1)); - push(&sym->type); -} - -static void -getname(char *t, union tokenop u) -{ - push((*++t) ? xstrdup(t) : NULL); -} - -static void -symbol(char *token, union tokenop u) -{ - Node *np = node(u.op & 0xFF); - Symbol *sym = getsym(atoi(token+1)); - - sclass = u.op >> 8; - np->u.sym = sym; - np->type = sym->type; - push(np); -} - -static Type * -gettype(char *token) -{ - struct decoc *dp; - - dp = &optbl[*token]; - if (!dp->parse) - error(ESYNTAX); - (*dp->parse)(token, dp->u); - return pop(); -} - -static void -constant(char *token, union tokenop u) -{ - static char letters[] = "0123456789ABCDEF"; - Node *np; - TUINT v; - unsigned c; - - ++token; - if (*token == '"') { - ++token; - np = node(OSTRING); - np->type.flags = STRF; - np->type.size = strlen(token); - np->type.align = int8type.align; - np->u.s = xstrdup(token); - } else { - np = node(OCONST); - np->type = *gettype(token++); - for (v = 0; c = *token++; v += c) { - v <<= 4; - c = strchr(letters, c) - letters; - } - np->u.i = v; - } - push(np); -} - -static void -assign(char *token, union tokenop u) -{ - int subop; - Node *np = node(u.op); - - switch (subop = *++token) { - case '+': - case '-': - case '*': - case '%': - case '/': - case 'l': - case 'r': - case '&': - case '|': - case '^': - case 'i': - case 'd': - ++token; - subop = optbl[subop].u.op; - break; - default: - subop = 0; - break; - } - - np->u.subop = subop; - np->type = *gettype(token); - np->right = pop(); - np->left = pop(); - push(np); -} - -static void -ternary(char *token, union tokenop u) -{ - Node *ask = node(OASK), *colon = node(OCOLON); - Type *tp = gettype(token+1); - - colon->right = pop(); - colon->left = pop(); - - ask->type = *tp; - ask->left = pop(); - ask->right = colon; - push(ask); -} - -static void -eval(char *tok) -{ - struct decoc *dp; - - do { - dp = &optbl[*tok]; - if (!dp->parse) - break; - (*dp->parse)(tok, dp->u); - } while (tok = strtok(NULL, "\t\n")); -} - -static int -nextline(void) -{ - static char line[LINESIZ]; - size_t len; - int c; - void (*fun)(void); - -repeat: - ++lineno; - if (!fgets(line, sizeof(line), stdin)) - return 0; - if ((len = strlen(line)) == 0 || line[0] == '\n') - goto repeat; - if (line[len-1] != '\n') - error(len < sizeof(line)-1 ? ELNBLNE : ELNLINE); - line[len-1] = '\0'; - - c = *line; - eval(strtok(line, "\t\n")); - if ((fun = *optbl[c].eval) != NULL) - (*fun)(); - if (sp != stack) - error(ESTACKA); - return 1; -} - -static void -oreturn(char *token, union tokenop u) -{ - Node *np = node(u.op); - - if (token = strtok(NULL, "\t\n")) - eval(token); - if (!empty()) - np->left = pop(); - push(np); -} - -/* - * Move np (which is a OCASE/ODEFAULT/OESWITCH) to be contigous with - * the last switch table. It is a bit ugly to touch directly curstmt - * here, but moving this function to node.c is worse, because we are - * putting knowledge of how the text is parsed into the node - * represtation module. - */ -static void -waft(Node *np) -{ - Node *lastcase, *next;; - struct swtch *cur; - extern Node *curstmt; - - if (swp == swtbl) - error(EWTACKU); - - cur = swp - 1; - lastcase = cur->last; - next = lastcase->next; - - np->next = next; - np->prev = lastcase; - - if (next) - next->prev = np; - lastcase->next = np; - - if (curstmt == cur->last) - curstmt = np; - cur->last = np; - cur->nr++; -} - -static void -bswitch(char *token, union tokenop u) -{ - struct swtch *cur; - Node *np = node(u.op); - - if (swp == &swtbl[NR_BLOCK]) - error(EWTACKO); - cur = swp++; - cur->nr = 0; - - eval(strtok(NULL, "\t\n")); - np->left = pop(); - - push(cur->first = cur->last = np); -} - -static void -eswitch(char *token, union tokenop u) -{ - struct swtch *cur; - - if (swp == swtbl) - error(EWTACKU); - jump(token, u); - waft(pop()); - cur = --swp; - cur->first->u.i = cur->nr; -} - -static void -ocase(char *token, union tokenop u) -{ - jump(token, u); - waft(pop()); -} - -static void -jump(char *token, union tokenop u) -{ - Node *aux, *np = node(u.op); - - eval(strtok(NULL, "\t\n")); - - if (u.op == OBRANCH || u.op == OCASE) - np->left = pop(); - aux = pop(); - np->u.sym = aux->u.sym; - delnode(aux); - push(np); -} - -static void -loop(char *token, union tokenop u) -{ - push(node(u.op)); -} - -static void -unary(char *token, union tokenop u) -{ - Node *np = node(u.op); - - np->type = *gettype(token+1); - np->left = pop(); - np->right = NULL; - push(np); -} - -static void -call(char *token, union tokenop u) -{ - Node *np, *par, *fun = node(u.op); - - for (par = NULL;; par = np) { - np = pop(); - if (np->op != OPAR) - break; - np->right = par; - } - - fun->type = *gettype(token+1); - fun->left = np; - fun->right = par; - push(fun); -} - -static void -builtin(char *token, union tokenop u) -{ - Node *np = node(u.op); - char *name; - unsigned subop, nchilds; - - np->type = *gettype(token+1); - name = pop(); - - if (!strcmp("__builtin_va_arg", name)) { - nchilds = 1; - subop = BVA_ARG; - } else if (!strcmp("__builtin_va_start", name)) { - nchilds = 2; - subop = BVA_START; - } else if (!strcmp("__builtin_va_end", name)) { - nchilds = 1; - subop = BVA_END; - } else if (!strcmp("__builtin_va_copy", name)) { - nchilds = 2; - subop = BVA_COPY; - } else { - error(EBBUILT);; - } - - np->u.subop = subop; - np->right = (nchilds == 2) ? pop() : NULL; - np->left = (nchilds != 0) ? pop() : NULL; - - free(name); - push(np); -} - -static void -binary(char *token, union tokenop u) -{ - Node *np = node(u.op); - - np->type = *gettype(token+1); - np->right = pop(); - np->left = pop(); - push(np); -} - -static void -binit(char *token, union tokenop u) -{ - ininit = 1; -} - -static void -einit(char *token, union tokenop u) -{ - ininit = 0; - endinit(); -} - -static void -endpars(void) -{ - if (!curfun || !inpars) - error(ESYNTAX); - inpars = 0; -} - -static void -aggregate(void) -{ - Node *align, *size; - char *name; - Type *tp; - Symbol *sym; - - align = pop(); - size = pop(); - name = pop(); - tp = pop(); - - tp->size = size->u.i; - tp->align = align->u.i; - tp->flags = AGGRF; - /* - * type is the first field of Symbol so we can obtain the - * address of the symbol from the address of the type. - * We have to do this because composed returns the pointer - * to the type, but in this function we also need the - * symbol to store the name. - */ - sym = (Symbol *) tp; - sym->name = name; - - delnode(align); - delnode(size); -} - -static void -array(void) -{ - Type *tp, *base; - Node *size; - - size = pop(); - base = pop(); - tp = pop(); - tp->size = size->u.i * base->size; /* FIXME check for overflow */ - tp->align = base->align; - - delnode(size); -} - -static void -decl(Symbol *sym) -{ - Type *tp = &sym->type; - - if (tp->flags & FUNF) { - lastfun = sym; - } else { - switch (sym->kind) { - case SEXTRN: - case SGLOB: - case SPRIV: - case SLOCAL: - defglobal(sym); - break; - case SAUTO: - case SREG: - if (!curfun) - error(ESYNTAX); - ((inpars) ? defpar : defvar)(sym); - break; - default: - abort(); - } - } -} - -static void -vardecl(void) -{ - Type *tp, *rp; - Node *np; - Symbol *sym; - char *name; - - name = pop(); - tp = pop(); - if (tp->flags & FUNF) - rp = pop(); - np = pop(); - - sym = np->u.sym; - /* - * We have to free sym->name because in tentative declarations - * we can have multiple declarations of the same symbol, and in - * this case our parser will allocate twice the memory - */ - free(sym->name); - sym->name = name; - sym->type = *tp; - if (tp->flags & FUNF) - sym->rtype = *rp; - sym->kind = sclass; - - if (ininit) - sym->type.flags |= INITF; - decl(sym); - delnode(np); -} - -static void -flddecl(void) -{ - Node *off, *np; - char *name; - Type *tp; - Symbol *sym; - - off = pop(); - name = pop(); - tp = pop(); - np = pop(); - - sym = np->u.sym; - sym->u.off = off->u.i; - sym->name = name; - sym->type = *tp; - - delnode(np); - delnode(off); -} - -static void -labeldcl(void) -{ - Node *np; - Symbol *sym; - - np = pop(); - np->op = ONOP; - sym = np->u.sym; - sym->kind = SLABEL; - sym->u.stmt = np; - np->label = sym; - addstmt(np, SETCUR); -} - -static void -stmt(void) -{ - Node *np; - - if (empty()) - return; - np = pop(); - if (ininit) { - data(np); - deltree(np); - return; - } - addstmt(np, SETCUR); -} - -static void -beginfun(void) -{ - curfun = lastfun; - inpars = 1; - pushctx(); - addstmt(node(OBFUN), SETCUR); -} - -static void -endfun(void) -{ - endf = 1; - addstmt(node(OEFUN), SETCUR); -} - -void -parse(void) -{ - cleannodes(); /* remove code of previous function */ - popctx(); /* remove context of previous function */ - curfun = NULL; - endf = 0; - - while (!endf && nextline()) - ; - if (ferror(stdin)) - error(EFERROR, strerror(errno)); -} diff --git a/cc2/peep.c b/cc2/peep.c @@ -1,8 +0,0 @@ -static char sccsid[] = "@(#) ./cc2/peep.c"; -#include "../inc/scc.h" -#include "cc2.h" - -void -peephole(void) -{ -} diff --git a/cc2/symbol.c b/cc2/symbol.c @@ -1,92 +0,0 @@ -static char sccsid[] = "@(#) ./cc2/symbol.c"; -#include <limits.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "../inc/scc.h" - -#include "cc2.h" - -#define NR_SYMHASH 64 - -Symbol *locals; - -static Symbol *symtab[NR_SYMHASH], *curlocal; -static int infunction; - - -void -freesym(Symbol *sym) -{ - free(sym->name); - free(sym); -} - -void -pushctx(void) -{ - infunction = 1; -} - -void -popctx(void) -{ - Symbol *sym, *next; - - infunction = 0; - for (sym = locals; sym; sym = next) { - next = sym->next; - /* - * Symbols are inserted in the hash in the inverted - * order they are found in locals and it is impossible - * to have a global over a local, because a local is - * any symbol defined in the body of a function, - * even if it has extern linkage. - * For this reason when we reach a symbol in the - * locals list we know that it is the head of it - * collision list and we can remove it assigning - * it h_next to the hash table position - */ - if (sym->id != TMPSYM) - symtab[sym->id & NR_SYMHASH-1] = sym->h_next; - freesym(sym); - } - curlocal = locals = NULL; -} - -Symbol * -getsym(unsigned id) -{ - Symbol **htab, *sym; - static unsigned short num; - - if (id >= USHRT_MAX) - error(EBADID); - - if (id != TMPSYM) { - htab = &symtab[id & NR_SYMHASH-1]; - for (sym = *htab; sym; sym = sym->h_next) { - if (sym->id == id) - return sym; - } - } - - sym = xcalloc(1, sizeof(*sym)); - sym->id = id; - if (infunction) { - if (!locals) - locals = sym; - if (curlocal) - curlocal->next = sym; - curlocal = sym; - } - if (id != TMPSYM) { - sym->h_next = *htab; - *htab = sym; - } - if ((sym->numid = ++num) == 0) - error(EIDOVER); - - return sym; -} diff --git a/cc2/target/amd64-sysv/cgen.c b/cc2/target/amd64-sysv/cgen.c @@ -1,15 +0,0 @@ -static char sccsid[] = "@(#) ./cc2/arch/amd64-sysv/cgen.c"; - -#include "arch.h" -#include "../../../inc/scc.h" -#include "../../cc2.h" - -Node * -cgen(Node *np) -{ -} - -Node * -sethi(Node *np) -{ -} diff --git a/cc2/target/amd64-sysv/code.c b/cc2/target/amd64-sysv/code.c @@ -1,210 +0,0 @@ -static char sccsid[] = "@(#) ./cc2/arch/amd64-sysv/code.c"; - -#include <stdio.h> -#include <stdlib.h> - -#include <cstd.h> -#include "arch.h" -#include "../../../inc/scc.h" -#include "../../cc2.h" - -enum segment { - CODESEG, - DATASEG, - BSSSEG, - NOSEG -}; - -static int curseg = NOSEG; - -static void -segment(int seg) -{ - static char *txt[] = { - [CODESEG] = "\t.text\n", - [DATASEG] = "\t.data\n", - [BSSSEG] = "\t.bss\n", - }; - - if (seg == curseg) - return; - fputs(txt[seg], stdout); - curseg = seg; -} - -static char * -symname(Symbol *sym) -{ - static char name[INTIDENTSIZ+1]; - - if (sym->name) { - switch (sym->kind) { - case SEXTRN: - case SGLOB: - case SPRIV: - return sym->name; - } - } - - sprintf(name, ".L%d", sym->numid); - - return name; -} - -static void -emitconst(Node *np) -{ - switch (np->type.size) { - case 1: - printf("%d", (int) np->u.i & 0xFF); - break; - case 2: - printf("%d", (int) np->u.i & 0xFFFF); - break; - case 4: - printf("%ld", (long) np->u.i & 0xFFFFFFFF); - break; - case 8: - printf("%lld", (long long) np->u.i & 0xFFFFFFFF); - break; - default: - abort(); - } -} - -static void -emittree(Node *np) -{ - if (!np) - return; - - switch (np->op) { - case OSTRING: - printf("\"%s\"", np->u.s); - free(np->u.s); - np->u.s = NULL; - break; - case OCONST: - emitconst(np); - break; - case OADDR: - emittree(np->left); - break; - case OMEM: - fputs(symname(np->u.sym), stdout); - break; - default: - emittree(np->left); - printf(" %c ", np->op); - emittree(np->right); - break; - } -} -static void -size2asm(Type *tp) -{ - char *s; - - if (tp->flags & STRF) { - s = "\t.ascii\t"; - } else { - switch (tp->size) { - case 1: - s = "\t.byte\t"; - break; - case 2: - s = "\t.short\t"; - break; - case 4: - s = "\t.long\t"; - break; - case 8: - s = "\t.quad\t"; - break; - default: - s = "\t.space\t%lu,"; - break; - } - } - printf(s, tp->size); -} - - -void -data(Node *np) -{ - size2asm(&np->type); - emittree(np); - putchar('\n'); -} - -static void -label(Symbol *sym) -{ - int seg; - char *name = symname(sym); - Type *tp = &sym->type; - - if (sym->type.flags & FUNF) - seg = CODESEG; - else if (sym->type.flags & INITF) - seg = DATASEG; - else - seg = BSSSEG; - segment(seg); - - switch (sym->kind) { - case SEXTRN: - printf("\t.extern\t%s\n", name); - case SLOCAL: - return; - case SGLOB: - printf("\t.global\t%s\n", name); - if (seg == BSSSEG) - printf("\t.comm\t%s,%lu\n", name, tp->size); - break; - } - if (sym->type.align != 1) - printf("\t.align\t%lu\n", sym->type.align ); - printf("%s:\n", name); -} - -void -defglobal(Symbol *sym) -{ - label(sym); - if (sym->kind == SEXTRN || (sym->type.flags & INITF)) - return; - size2asm(&sym->type); - puts("0"); -} - -void -defvar(Symbol *sym) -{ -} - -void -defpar(Symbol *sym) -{ -} - -void -newfun(void) -{ -} - -void -writeout(void) -{ -} - -void -endinit(void) -{ -} - -void -getbblocks(void) -{ -} diff --git a/cc2/target/amd64-sysv/optm.c b/cc2/target/amd64-sysv/optm.c @@ -1,10 +0,0 @@ -static char sccsid[] = "@(#) ./cc2/arch/amd64-sysv/optm.c"; - -#include "../../../inc/scc.h" -#include "../../cc2.h" - -Node * -optm_dep(Node *np) -{ - return np; -} diff --git a/cc2/target/amd64-sysv/target.mk b/cc2/target/amd64-sysv/target.mk @@ -1,9 +0,0 @@ - -OBJ-amd64-sysv = $(OBJ) \ - target/amd64-sysv/cgen.o \ - target/amd64-sysv/optm.o \ - target/amd64-sysv/code.o \ - target/amd64-sysv/types.o - -$(LIBEXEC)/cc2-amd64-sysv: $(OBJ-amd64-sysv) - $(CC) $(SCC_LDFLAGS) $(OBJ-amd64-sysv) -lscc -o $@ diff --git a/cc2/target/amd64-sysv/types.c b/cc2/target/amd64-sysv/types.c @@ -1,93 +0,0 @@ -static char sccsid[] = "@(#) ./cc2/arch/amd64-sysv/types.c"; - -#include "../../../inc/scc.h" -#include "../../cc2.h" - - -Type int8type = { - .flags = SIGNF | INTF, - .size = 1, - .align = 1 -}; - -Type int16type = { - .flags = SIGNF | INTF, - .size = 2, - .align = 2 -}; - -Type int32type = { - .flags = SIGNF | INTF, - .size = 4, - .align = 4 -}; - -Type int64type = { - .flags = SIGNF | INTF, - .size = 8, - .align = 8 -}; - -Type uint8type = { - .flags = INTF, - .size = 1, - .align = 1 -}; - -Type uint16type = { - .flags = INTF, - .size = 2, - .align = 2 -}; - -Type uint32type = { - .flags = INTF, - .size = 4, - .align = 4 -}; - -Type uint64type = { - .flags = INTF, - .size = 8, - .align = 2 -}; - -Type ptrtype = { - .flags = INTF, - .size = 8, - .align = 8 -}; - -Type booltype = { - .flags = INTF, - .size = 1, - .align = 1 -}; - -Type float32type = { - .flags = FLOATF, - .size = 4, - .align = 4 -}; - -Type float64type = { - .flags = FLOATF, - .size = 8, - .align = 8 -}; - -Type float80type = { - .flags = FLOATF, - .size = 16, - .align = 16 -}; - -Type voidtype = { - .size = 0, - .align = 0 -}; - -Type arg_type = { - .size = 24, - .align = 8 -}; diff --git a/cc2/target/i386-sysv/cgen.c b/cc2/target/i386-sysv/cgen.c @@ -1,15 +0,0 @@ -static char sccsid[] = "@(#) ./cc2/arch/i386-sysv/cgen.c"; - -#include "arch.h" -#include "../../../inc/scc.h" -#include "../../cc2.h" - -Node * -cgen(Node *np) -{ -} - -Node * -sethi(Node *np) -{ -} diff --git a/cc2/target/i386-sysv/code.c b/cc2/target/i386-sysv/code.c @@ -1,208 +0,0 @@ -static char sccsid[] = "@(#) ./cc2/arch/i386-sysv/code.c"; -#include <stdio.h> -#include <stdlib.h> - -#include <cstd.h> -#include "arch.h" -#include "../../../inc/scc.h" -#include "../../cc2.h" - -enum segment { - CODESEG, - DATASEG, - BSSSEG, - NOSEG -}; - -static int curseg = NOSEG; - -static void -segment(int seg) -{ - static char *txt[] = { - [CODESEG] = "\t.text\n", - [DATASEG] = "\t.data\n", - [BSSSEG] = "\t.bss\n", - }; - - if (seg == curseg) - return; - fputs(txt[seg], stdout); - curseg = seg; -} - -static char * -symname(Symbol *sym) -{ - static char name[INTIDENTSIZ+1]; - - if (sym->name) { - switch (sym->kind) { - case SEXTRN: - case SGLOB: - case SPRIV: - return sym->name; - } - } - - sprintf(name, ".L%d", sym->numid); - - return name; -} - -static void -emitconst(Node *np) -{ - switch (np->type.size) { - case 1: - printf("%d", (int) np->u.i & 0xFF); - break; - case 2: - printf("%d", (int) np->u.i & 0xFFFF); - break; - case 4: - printf("%ld", (long) np->u.i & 0xFFFFFFFF); - break; - case 8: - printf("%lld", (long long) np->u.i & 0xFFFFFFFF); - break; - default: - abort(); - } -} - -static void -emittree(Node *np) -{ - if (!np) - return; - - switch (np->op) { - case OSTRING: - printf("\"%s\"", np->u.s); - free(np->u.s); - np->u.s = NULL; - break; - case OCONST: - emitconst(np); - break; - case OADDR: - emittree(np->left); - break; - case OMEM: - fputs(symname(np->u.sym), stdout); - break; - default: - emittree(np->left); - printf(" %c ", np->op); - emittree(np->right); - break; - } -} -static void -size2asm(Type *tp) -{ - char *s; - - if (tp->flags & STRF) { - s = "\t.ascii\t"; - } else { - switch (tp->size) { - case 1: - s = "\t.byte\t"; - break; - case 2: - s = "\t.short\t"; - break; - case 4: - s = "\t.long\t"; - break; - case 8: - s = "\t.quad\t"; - break; - default: - s = "\t.space\t%lu,"; - break; - } - } - printf(s, tp->size); -} - -void -data(Node *np) -{ - size2asm(&np->type); - emittree(np); - putchar('\n'); -} - -static void -label(Symbol *sym) -{ - int seg; - char *name = symname(sym); - Type *tp = &sym->type; - - if (sym->type.flags & FUNF) - seg = CODESEG; - else if (sym->type.flags & INITF) - seg = DATASEG; - else - seg = BSSSEG; - segment(seg); - - switch (sym->kind) { - case SEXTRN: - printf("\t.extern\t%s\n", name); - case SLOCAL: - return; - case SGLOB: - printf("\t.global\t%s\n", name); - if (seg == BSSSEG) - printf("\t.comm\t%s,%lu\n", name, tp->size); - break; - } - if (sym->type.align != 1) - printf("\t.align\t%lu\n", sym->type.align ); - printf("%s:\n", name); -} - -void -defglobal(Symbol *sym) -{ - label(sym); - if (sym->kind == SEXTRN || (sym->type.flags & INITF)) - return; - size2asm(&sym->type); - puts("0"); -} - -void -defpar(Symbol *sym) -{ -} - -void -defvar(Symbol *sym) -{ -} - -void -newfun(void) -{ -} - -void -writeout(void) -{ -} - -void -endinit(void) -{ -} - -void -getbblocks(void) -{ -} diff --git a/cc2/target/i386-sysv/optm.c b/cc2/target/i386-sysv/optm.c @@ -1,10 +0,0 @@ -static char sccsid[] = "@(#) ./cc2/arch/i386-sysv/optm.c"; - -#include "../../../inc/scc.h" -#include "../../cc2.h" - -Node * -optm_dep(Node *np) -{ - return np; -} diff --git a/cc2/target/i386-sysv/target.mk b/cc2/target/i386-sysv/target.mk @@ -1,9 +0,0 @@ - -OBJ-i386-sysv = $(OBJ) \ - target/i386-sysv/cgen.o \ - target/i386-sysv/optm.o \ - target/i386-sysv/code.o \ - target/i386-sysv/types.o - -$(LIBEXEC)/cc2-i386-sysv: $(OBJ-i386-sysv) - $(CC) $(SCC_LDFLAGS) $(OBJ-i386-sysv) -lscc -o $@ diff --git a/cc2/target/i386-sysv/types.c b/cc2/target/i386-sysv/types.c @@ -1,94 +0,0 @@ -static char sccsid[] = "@(#) ./cc2/arch/i386-sysv/types.c"; - -#include "../../../inc/scc.h" -#include "../../cc2.h" - - -Type int8type = { - .flags = SIGNF | INTF, - .size = 1, - .align = 1 -}; - -Type int16type = { - .flags = SIGNF | INTF, - .size = 2, - .align = 2 -}; - -Type int32type = { - .flags = SIGNF | INTF, - .size = 4, - .align = 4 -}; - -Type int64type = { - .flags = SIGNF | INTF, - .size = 8, - .align = 4 -}; - -Type uint8type = { - .flags = INTF, - .size = 1, - .align = 1 -}; - -Type uint16type = { - .flags = INTF, - .size = 2, - .align = 2 -}; - -Type uint32type = { - .flags = INTF, - .size = 4, - .align = 2 -}; - -Type uint64type = { - .flags = INTF, - .size = 8, - .align = 4 -}; - -Type ptrtype = { - .flags = INTF, - .size = 4, - .align = 4 -}; - -Type booltype = { - .flags = INTF, - .size = 1, - .align = 1 -}; - -Type float32type = { - .flags = FLOATF, - .size = 4, - .align = 4 -}; - -Type float64type = { - .flags = FLOATF, - .size = 8, - .align = 4 -}; - -Type float80type = { - .flags = FLOATF, - .size = 12, - .align = 4 -}; - -Type voidtype = { - .size = 0, - .align = 0 -}; - -/* this type is not used in this architecture */ -Type arg_type = { - .size = 0, - .align = 0 -}; diff --git a/cc2/target/qbe/cgen.c b/cc2/target/qbe/cgen.c @@ -1,728 +0,0 @@ -static char sccsid[] = "@(#) ./cc2/arch/qbe/cgen.c"; - -#include <assert.h> -#include <stdlib.h> - -#include <cstd.h> -#include "arch.h" -#include "../../../inc/scc.h" -#include "../../cc2.h" - -enum sflags { - ISTMP = 1, - ISCONS = 2 -}; - -static char opasmw[] = { - [OADD] = ASADDW, - [OSUB] = ASSUBW, - [OMUL] = ASMULW, - [OMOD] = ASMODW, - [ODIV] = ASDIVW, - [OSHL] = ASSHLW, - [OSHR] = ASSHRW, - [OLT] = ASLTW, - [OGT] = ASGTW, - [OLE] = ASLEW, - [OGE] = ASGEW, - [OEQ] = ASEQW, - [ONE] = ASNEW, - [OBAND] = ASBANDW, - [OBOR] = ASBORW, - [OBXOR] = ASBXORW, -}; - -static char opasml[] = { - [OADD] = ASADDL, - [OSUB] = ASSUBL, - [OMUL] = ASMULL, - [OMOD] = ASMODL, - [ODIV] = ASDIVL, - [OSHL] = ASSHLL, - [OSHR] = ASSHRL, - [OLT] = ASLTL, - [OGT] = ASGTL, - [OLE] = ASLEL, - [OGE] = ASGEL, - [OEQ] = ASEQL, - [ONE] = ASNEL, - [OBAND] = ASBANDL, - [OBOR] = ASBORL, - [OBXOR] = ASBXORL, -}; - -static char opasms[] = { - [OADD] = ASADDS, - [OSUB] = ASSUBS, - [OMUL] = ASMULS, - [ODIV] = ASDIVS, - [OLT] = ASLTS, - [OGT] = ASGTS, - [OLE] = ASLES, - [OGE] = ASGES, - [OEQ] = ASEQS, - [ONE] = ASNES, -}; -static char opasmd[] = { - [OADD] = ASADDD, - [OSUB] = ASSUBD, - [OMUL] = ASMULD, - [ODIV] = ASDIVD, - [OLT] = ASLTD, - [OGT] = ASGTD, - [OLE] = ASLED, - [OGE] = ASGED, - [OEQ] = ASEQD, - [ONE] = ASNED, -}; - -extern Type int32type, uint32type, ptrtype; - -static Node * -tmpnode(Node *np, Type *tp) -{ - char flags; - Symbol *sym; - - if (!np) - np = node(OTMP); - sym = getsym(TMPSYM); - sym->type = np->type = *tp; - flags = tp->flags & ~(PARF|INITF); - sym->type.flags = np->type.flags = flags; - sym->kind = STMP; - np->left = np->right = NULL; - np->u.sym = sym; - np->op = OTMP; - np->flags |= ISTMP; - return np; -} - -static Node * -load(Type *tp, Node *np, Node *new) -{ - int op; - int flags = tp->flags; - - if (flags & (AGGRF|FUNF)) { - *new = *np; - return new; - } - switch (tp->size) { - case 1: - op = ASLDSB; - break; - case 2: - op = ASLDSH; - break; - case 4: - op = (flags & FLOATF) ? ASLDS : ASLDSW; - break; - case 8: - op = (flags & FLOATF) ? ASLDD : ASLDL; - break; - default: - abort(); - } - /* - * unsigned version of operations are always +1 the - * signed version - */ - if ((flags & (INTF|SIGNF)) == INTF && tp->size < 8) - ++op; - - code(op, tmpnode(new, tp), np, NULL); - - return new; -} - -static Node *rhs(Node *np, Node *new); - -static Node * -cast(Type *td, Node *ns, Node *nd) -{ - Type *ts; - Node aux1, aux2; - int op, d_isint, s_isint; - - ts = &ns->type; - d_isint = (td->flags & INTF) != 0; - s_isint = (ts->flags & INTF) != 0; - - if (d_isint && s_isint) { - if (td->size <= ts->size) { - *nd = *ns; - return nd; - } - assert(td->size == 4 || td->size == 8); - switch (ts->size) { - case 1: - op = (td->size == 4) ? ASEXTBW : ASEXTBL; - break; - case 2: - op = (td->size == 4) ? ASEXTHW : ASEXTHL; - break; - case 4: - op = ASEXTWL; - break; - default: - abort(); - } - /* - * unsigned version of operations are always +1 the - * signed version - */ - op += (ts->flags & SIGNF) == 0; - } else if (d_isint) { - /* conversion from float to int */ - switch (ts->size) { - case 4: - op = (td->size == 8) ? ASSTOL : ASSTOW; - break; - case 8: - op = (td->size == 8) ? ASDTOL : ASDTOW; - break; - default: - abort(); - } - /* TODO: Add signess */ - } else if (s_isint) { - /* conversion from int to float */ - switch (ts->size) { - case 1: - case 2: - ts = (ts->flags&SIGNF) ? &int32type : &uint32type; - ns = cast(ts, ns, tmpnode(&aux2, ts)); - case 4: - op = (td->size == 8) ? ASSWTOD : ASSWTOS; - break; - case 8: - op = (td->size == 8) ? ASSLTOD : ASSLTOS; - break; - default: - abort(); - } - /* TODO: Add signess */ - } else { - /* conversion from float to float */ - op = (td->size == 4) ? ASEXTS : ASTRUNCD; - } - - code(op, tmpnode(nd, td), ns, NULL); - return nd; -} - -static Node * -call(Node *np, Node *fun, Node *ret) -{ - int n, op; - Type *tp; - Node aux, **q, *p, *pars[NR_FUNPARAM]; - - for (n = 0, p = np->right; p; p = p->right) - pars[n++] = rhs(p->left, node(OTMP)); - - tp = &np->type; - code(ASCALL, tmpnode(ret, tp), fun, NULL); - - for (q = pars; q < &pars[n]; ++q) { - op = (q == &pars[n-1]) ? ASPARE : ASPAR; - tmpnode(&aux, &(*q)->type); - code(op, NULL, *q, &aux); - } - code((np->op == OCALL) ? ASCALLE : ASCALLEX, NULL, NULL, NULL); - - return ret; -} - -static Node * -assign(Type *tp, Node *to, Node *from) -{ - int op; - - switch (tp->size) { - case 1: - op = ASSTB; - break; - case 2: - op = ASSTH; - break; - case 4: - op = (tp->flags & FLOATF) ? ASSTS : ASSTW; - break; - case 8: - op = (tp->flags & FLOATF) ? ASSTD : ASSTL; - break; - default: - op = ASSTM; - break; - } - code(op, to, from, NULL); - return from; -} - -static Node * -copy(Type *tp, Node *to, Node *from) -{ - int op; - - switch (tp->size) { - case 1: - op = ASCOPYB; - break; - case 2: - op = ASCOPYH; - break; - case 4: - op = (tp->flags & FLOATF) ? ASCOPYS : ASCOPYW; - break; - case 8: - op = (tp->flags & FLOATF) ? ASCOPYD : ASCOPYL; - break; - default: - /* TODO: Need to handle the general case */ - abort(); - } - code(op, to, from, NULL); - return from; -} - -/* TODO: Do field() transformation in sethi */ - -static Node * -field(Node *np, Node *ret, int islhs) -{ - Node base, node, off, add, *addr; - TUINT offset = np->right->u.sym->u.off; - - addr = rhs(np->left, &base); - - if (offset != 0) { - node.op = OADD; - node.type = ptrtype; - node.left = addr; - node.right = constnode(&off, offset, &ptrtype); - addr = rhs(&node, &add); - } - - if (islhs) - *ret = *addr; - else - load(&np->type, addr, ret); - - return ret; -} - -static Node * -lhs(Node *np, Node *new) -{ - switch (np->op) { - case OMEM: - case OAUTO: - *new = *np; - return new; - case OPTR: - return rhs(np->left, new); - case OFIELD: - return field(np, new, 1); - default: - abort(); - } -} - -static void -bool(Node *np, Symbol *true, Symbol *false) -{ - Node *l = np->left, *r = np->right; - Node ret, ifyes, ifno; - Symbol *label; - - switch (np->op) { - case ONEG: - bool(l, false, true); - break; - case OAND: - label = newlabel(); - bool(l, label, false); - setlabel(label); - bool(r, true, false); - break; - case OOR: - label = newlabel(); - bool(l, true, label); - setlabel(label); - bool(r, true, false); - break; - default: - label2node(&ifyes, true); - label2node(&ifno, false); - code(ASBRANCH, rhs(np, &ret), &ifyes, &ifno); - break; - } -} - -static Node * -ternary(Node *np, Node *ret) -{ - Node ifyes, ifno, phi, *colon, aux1, aux2, aux3; - - tmpnode(ret, &np->type); - label2node(&ifyes, NULL); - label2node(&ifno, NULL); - label2node(&phi, NULL); - - colon = np->right; - code(ASBRANCH, rhs(np->left, &aux1), &ifyes, &ifno); - - setlabel(ifyes.u.sym); - copy(&ret->type, ret, rhs(colon->left, &aux2)); - code(ASJMP, NULL, &phi, NULL); - - setlabel(ifno.u.sym); - copy(&ret->type, ret, rhs(colon->right, &aux3)); - setlabel(phi.u.sym); - - return ret; -} - -static Node * -function(void) -{ - Node aux; - Symbol *p; - - /* allocate stack space for parameters */ - for (p = locals; p && (p->type.flags & PARF) != 0; p = p->next) - code(ASALLOC, label2node(&aux, p), NULL, NULL); - - /* allocate stack space for local variables) */ - for ( ; p && p->id != TMPSYM; p = p->next) { - if (p->kind != SAUTO) - continue; - code(ASALLOC, label2node(&aux, p), NULL, NULL); - } - /* store formal parameters in parameters */ - for (p = locals; p; p = p->next) { - if ((p->type.flags & PARF) == 0) - break; - code(ASFORM, label2node(&aux, p), NULL, NULL); - } - return NULL; -} - -static void -swtch_if(Node *idx) -{ - Node aux1, aux2, *np; - Symbol *deflabel = NULL; - - for (;;) { - np = delstmt(); - setlabel(np->label); - - switch (np->op) { - case OESWITCH: - if (!deflabel) - deflabel = np->u.sym; - aux1.op = OJMP; - aux1.label = NULL; - aux1.u.sym = deflabel; - cgen(&aux1); - return; - case OCASE: - aux1 = *np; - aux1.op = OBRANCH; - aux1.label = NULL; - aux1.left = &aux2; - - aux2.op = OEQ; - aux2.type = idx->type; - aux2.left = np->left; - aux2.right = idx; - - cgen(&aux1); - break; - case ODEFAULT: - deflabel = np->u.sym; - break; - default: - abort(); - } - } -} - -static Node * -rhs(Node *np, Node *ret) -{ - Node aux1, aux2, *phi, *l = np->left, *r = np->right; - Type *tp; - int off, op; - char *tbl; - Symbol *true, *false; - - tp = &np->type; - - switch (np->op) { - case OBFUN: - return function(); - case ONOP: - case OBLOOP: - case OELOOP: - case OEFUN: - return NULL; - case OTMP: - case OCONST: - *ret = *np; - return np; - case OMEM: - case OAUTO: - return load(tp, np, ret); - case ONEG: - case OAND: - case OOR: - true = newlabel(); - false = newlabel(); - phi = label2node(&aux1, NULL); - tmpnode(ret, &int32type); - - bool(np, true, false); - - setlabel(true); - code(ASCOPYW, ret, constnode(&aux2, 1, &int32type), NULL); - code(ASJMP, NULL, phi, NULL); - - setlabel(false); - code(ASCOPYW, ret, constnode(&aux2, 0, &int32type), NULL); - - setlabel(phi->u.sym); - return ret; - case OMOD: - case OSHR: - assert(tp->flags & INTF); - case ODIV: - case OLT: - case OGT: - case OLE: - case OGE: - /* - * unsigned version of operations are always +1 the - * signed version - */ - off = (tp->flags & SIGNF) == 0; - goto binary; - case OSHL: - case OBAND: - case OBOR: - case OBXOR: - assert(tp->flags & INTF); - case OADD: - case OSUB: - case OMUL: - case OEQ: - case ONE: - off = 0; - binary: - if (l->complex >= r->complex) { - rhs(l, &aux1); - rhs(r, &aux2); - } else { - rhs(r, &aux2); - rhs(l, &aux1); - } - switch (tp->size) { - case 4: - tbl = (tp->flags & FLOATF) ? opasms : opasmw; - break; - case 8: - tbl = (tp->flags & FLOATF) ? opasmd : opasml; - break; - default: - abort(); - } - op = tbl[np->op] + off; - tmpnode(ret, tp); - code(op, ret, &aux1, &aux2); - return ret; - case OCALL: - case OCALLE: - if (l->op == OPTR) - l = rhs(l, &aux1); - return call(np, l, ret); - case OCAST: - return cast(tp, rhs(l, &aux1), ret); - case OASSIG: - /* TODO: Do this transformations in sethi */ - switch (np->u.subop) { - case OINC: - op = OADD; - goto post_oper; - case ODEC: - op = OSUB; - post_oper: - aux1.op = op; - aux1.left = rhs(l, ret); - aux1.right = r; - aux1.type = np->type; - rhs(&aux1, &aux2); - lhs(l, &aux1); - assign(tp, &aux1, &aux2); - break; - default: - aux2.type = np->type; - aux2.op = np->u.subop; - aux2.right = np->right; - aux2.left = np->left; - r = rhs(&aux2, &aux1); - Node aux3; - if (l->op == OCAST) { - aux3.type = l->left->type; - aux3.op = OCAST; - aux3.left = r; - aux3.right = NULL; - r = &aux3; - l = l->left; - } - case 0: - /* TODO: see what is the most difficult */ - lhs(l, &aux2); - rhs(r, ret); - return assign(tp, &aux2, ret); - } - return ret; - case OASK: - return ternary(np, ret); - case OCOMMA: - rhs(l, &aux1); - return rhs(r, ret); - case OPTR: - return load(tp, rhs(l, &aux1), ret); - case OADDR: - lhs(l, ret); - ret->type = *tp; - return ret; - case OFIELD: - return field(np, ret, 0); - case OBUILTIN: - switch (np->u.subop) { - case BVA_START: - l = rhs(l, &aux1); - code(ASVSTAR, NULL, l, NULL); - return NULL; - case BVA_END: - return NULL; - case BVA_ARG: - l = rhs(l, &aux1); - code(ASVARG, tmpnode(ret, tp), l, NULL); - return ret; - case BVA_COPY: - /* TODO */ - default: - abort(); - } - default: - abort(); - } - abort(); -} - -Node * -cgen(Node *np) -{ - Node aux, *p, *next; - - setlabel(np->label); - switch (np->op) { - case OJMP: - label2node(&aux, np->u.sym); - code(ASJMP, NULL, &aux, NULL); - break; - case OBRANCH: - next = np->next; - if (!next->label) - next->label = newlabel(); - bool(np->left, np->u.sym, next->label); - break; - case ORET: - p = (np->left) ? rhs(np->left, &aux) : NULL; - code(ASRET, NULL, p, NULL); - break; - case OBSWITCH: - p = rhs(np->left, &aux); - swtch_if(p); - break; - default: - rhs(np, &aux); - break; - } - return NULL; -} - -/* - * This is strongly influenced by - * http://plan9.bell-labs.com/sys/doc/compiler.ps (/sys/doc/compiler.ps) - * calculate addresability as follows - * AUTO => 11 value+fp - * REG => 11 reg - * STATIC => 11 (value) - * CONST => 11 $value - * These values of addressability are not used in the code generation. - * They are only used to calculate the Sethi-Ullman numbers. Since - * QBE is AMD64 targered we could do a better job there, and try to - * detect some of the complex addressing modes of these processors. - */ -Node * -sethi(Node *np) -{ - Node *lp, *rp; - - if (!np) - return np; - - np->complex = 0; - np->address = 0; - lp = np->left; - rp = np->right; - - switch (np->op) { - case OAUTO: - case OREG: - case OMEM: - case OCONST: - np->address = 11; - break; - case OCPL: - assert(np->type.flags & INTF); - np->op = OBXOR; - rp = constnode(NULL, ~(TUINT) 0, &np->type); - goto binary; - case OSNEG: - np->op = OSUB; - rp = lp; - lp = constnode(NULL, 0, &np->type); - if ((np->type.flags & INTF) == 0) - lp->u.f = 0.0; - default: - binary: - lp = sethi(lp); - rp = sethi(rp); - break; - } - np->left = lp; - np->right = rp; - - if (np->address > 10) - return np; - if (lp) - np->complex = lp->complex; - if (rp) { - int d = np->complex - rp->complex; - - if (d == 0) - ++np->complex; - else if (d < 0) - np->complex = rp->complex; - } - if (np->complex == 0) - ++np->complex; - return np; -} diff --git a/cc2/target/qbe/code.c b/cc2/target/qbe/code.c @@ -1,568 +0,0 @@ -static char sccsid[] = "@(#) ./cc2/arch/qbe/code.c"; - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include <cstd.h> -#include "arch.h" -#include "../../../inc/scc.h" -#include "../../cc2.h" - -#define ADDR_LEN (INTIDENTSIZ+64) - -static void binary(void), unary(void), store(void), jmp(void), ret(void), - branch(void), call(void), ecall(void), param(void), - asalloc(void), form2local(void), ldir(void), vastart(void), - vaarg(void); - -static struct opdata { - void (*fun)(void); - char *txt; - char letter; -} optbl [] = { - [ASLDSB] = {.fun = unary, .txt = "loadsb", .letter = 'w'}, - [ASLDUB] = {.fun = unary, .txt = "loadub", .letter = 'w'}, - [ASLDSH] = {.fun = unary, .txt = "loadsh", .letter = 'w'}, - [ASLDUH] = {.fun = unary, .txt = "loaduh", .letter = 'w'}, - [ASLDSW] = {.fun = unary, .txt = "loadsw", .letter = 'w'}, - [ASLDUW] = {.fun = unary, .txt = "loaduw", .letter = 'w'}, - [ASLDL] = {.fun = unary, .txt = "loadl", .letter = 'l'}, - [ASLDS] = {.fun = unary, .txt = "loads", .letter = 's'}, - [ASLDD] = {.fun = unary, .txt = "loadd", .letter = 'd'}, - - [ASCOPYB] = {.fun = unary, .txt = "copy", .letter = 'b'}, - [ASCOPYH] = {.fun = unary, .txt = "copy", .letter = 'h'}, - [ASCOPYW] = {.fun = unary, .txt = "copy", .letter = 'w'}, - [ASCOPYL] = {.fun = unary, .txt = "copy", .letter = 'l'}, - [ASCOPYS] = {.fun = unary, .txt = "copy", .letter = 's'}, - [ASCOPYD] = {.fun = unary, .txt = "copy", .letter = 'd'}, - - [ASSTB] = {.fun = store, .txt = "store", .letter = 'b'}, - [ASSTH] = {.fun = store, .txt = "store", .letter = 'h'}, - [ASSTW] = {.fun = store, .txt = "store", .letter = 'w'}, - [ASSTL] = {.fun = store, .txt = "store", .letter = 'l'}, - [ASSTM] = {.fun = ldir}, - [ASSTS] = {.fun = store, .txt = "store", .letter = 's'}, - [ASSTD] = {.fun = store, .txt = "store", .letter = 'd'}, - - [ASADDW] = {.fun = binary, .txt = "add", .letter = 'w'}, - [ASSUBW] = {.fun = binary, .txt = "sub", .letter = 'w'}, - [ASMULW] = {.fun = binary, .txt = "mul", .letter = 'w'}, - [ASMODW] = {.fun = binary, .txt = "rem", .letter = 'w'}, - [ASUMODW] = {.fun = binary, .txt = "urem", .letter = 'w'}, - [ASDIVW] = {.fun = binary, .txt = "div", .letter = 'w'}, - [ASUDIVW] = {.fun = binary, .txt = "udiv", .letter = 'w'}, - [ASSHLW] = {.fun = binary, .txt = "shl", .letter = 'w'}, - [ASSHRW] = {.fun = binary, .txt = "sar", .letter = 'w'}, - [ASUSHRW] = {.fun = binary, .txt = "shr", .letter = 'w'}, - [ASLTW] = {.fun = binary, .txt = "csltw", .letter = 'w'}, - [ASULTW] = {.fun = binary, .txt = "cultw", .letter = 'w'}, - [ASGTW] = {.fun = binary, .txt = "csgtw", .letter = 'w'}, - [ASUGTW] = {.fun = binary, .txt = "cugtw", .letter = 'w'}, - [ASLEW] = {.fun = binary, .txt = "cslew", .letter = 'w'}, - [ASULEW] = {.fun = binary, .txt = "culew", .letter = 'w'}, - [ASGEW] = {.fun = binary, .txt = "csgew", .letter = 'w'}, - [ASUGEW] = {.fun = binary, .txt = "cugew", .letter = 'w'}, - [ASEQW] = {.fun = binary, .txt = "ceqw", .letter = 'w'}, - [ASNEW] = {.fun = binary, .txt = "cnew", .letter = 'w'}, - [ASBANDW] = {.fun = binary, .txt = "and", .letter = 'w'}, - [ASBORW] = {.fun = binary, .txt = "or", .letter = 'w'}, - [ASBXORW] = {.fun = binary, .txt = "xor", .letter = 'w'}, - - [ASADDL] = {.fun = binary, .txt = "add", .letter = 'l'}, - [ASSUBL] = {.fun = binary, .txt = "sub", .letter = 'l'}, - [ASMULL] = {.fun = binary, .txt = "mul", .letter = 'l'}, - [ASMODL] = {.fun = binary, .txt = "rem", .letter = 'l'}, - [ASUMODL] = {.fun = binary, .txt = "urem", .letter = 'l'}, - [ASDIVL] = {.fun = binary, .txt = "div", .letter = 'l'}, - [ASUDIVL] = {.fun = binary, .txt = "udiv", .letter = 'l'}, - [ASSHLL] = {.fun = binary, .txt = "shl", .letter = 'l'}, - [ASSHRL] = {.fun = binary, .txt = "sar", .letter = 'l'}, - [ASUSHRL] = {.fun = binary, .txt = "shr", .letter = 'l'}, - [ASLTL] = {.fun = binary, .txt = "csltl", .letter = 'w'}, - [ASULTL] = {.fun = binary, .txt = "cultl", .letter = 'w'}, - [ASGTL] = {.fun = binary, .txt = "csgtl", .letter = 'w'}, - [ASUGTL] = {.fun = binary, .txt = "cugtl", .letter = 'w'}, - [ASLEL] = {.fun = binary, .txt = "cslel", .letter = 'w'}, - [ASULEL] = {.fun = binary, .txt = "culel", .letter = 'w'}, - [ASGEL] = {.fun = binary, .txt = "csgel", .letter = 'w'}, - [ASUGEL] = {.fun = binary, .txt = "cugel", .letter = 'w'}, - [ASEQL] = {.fun = binary, .txt = "ceql", .letter = 'w'}, - [ASNEL] = {.fun = binary, .txt = "cnel", .letter = 'w'}, - [ASBANDL] = {.fun = binary, .txt = "and", .letter = 'l'}, - [ASBORL] = {.fun = binary, .txt = "or", .letter = 'l'}, - [ASBXORL] = {.fun = binary, .txt = "xor", .letter = 'l'}, - - [ASADDS] = {.fun = binary, .txt = "add", .letter = 's'}, - [ASSUBS] = {.fun = binary, .txt = "sub", .letter = 's'}, - [ASMULS] = {.fun = binary, .txt = "mul", .letter = 's'}, - [ASDIVS] = {.fun = binary, .txt = "div", .letter = 's'}, - [ASLTS] = {.fun = binary, .txt = "clts", .letter = 'w'}, - [ASGTS] = {.fun = binary, .txt = "cgts", .letter = 'w'}, - [ASLES] = {.fun = binary, .txt = "cles", .letter = 'w'}, - [ASGES] = {.fun = binary, .txt = "cges", .letter = 'w'}, - [ASEQS] = {.fun = binary, .txt = "ceqs", .letter = 'w'}, - [ASNES] = {.fun = binary, .txt = "cnes", .letter = 'w'}, - - [ASADDD] = {.fun = binary, .txt = "add", .letter = 'd'}, - [ASSUBD] = {.fun = binary, .txt = "sub", .letter = 'd'}, - [ASMULD] = {.fun = binary, .txt = "mul", .letter = 'd'}, - [ASDIVD] = {.fun = binary, .txt = "div", .letter = 'd'}, - [ASLTD] = {.fun = binary, .txt = "cltd", .letter = 'w'}, - [ASGTD] = {.fun = binary, .txt = "cgtd", .letter = 'w'}, - [ASLED] = {.fun = binary, .txt = "cled", .letter = 'w'}, - [ASGED] = {.fun = binary, .txt = "cged", .letter = 'w'}, - [ASEQD] = {.fun = binary, .txt = "ceqd", .letter = 'w'}, - [ASNED] = {.fun = binary, .txt = "cned", .letter = 'w'}, - - [ASEXTBW] = {.fun = unary, .txt = "extsb", .letter = 'w'}, - [ASUEXTBW]= {.fun = unary, .txt = "extub", .letter = 'w'}, - [ASEXTBL] = {.fun = unary, .txt = "extsb", .letter = 'l'}, - [ASUEXTBL]= {.fun = unary, .txt = "extub", .letter = 'l'}, - [ASEXTHW] = {.fun = unary, .txt = "extsh", .letter = 'w'}, - [ASUEXTHW]= {.fun = unary, .txt = "extuh", .letter = 'w'}, - [ASEXTWL] = {.fun = unary, .txt = "extsw", .letter = 'l'}, - [ASUEXTWL]= {.fun = unary, .txt = "extuw", .letter = 'l'}, - - [ASSTOL] = {.fun = unary, .txt = "stosi", .letter = 'l'}, - [ASSTOW] = {.fun = unary, .txt = "stosi", .letter = 'w'}, - [ASDTOL] = {.fun = unary, .txt = "dtosi", .letter = 'l'}, - [ASDTOW] = {.fun = unary, .txt = "dtosi", .letter = 'w'}, - - [ASSWTOD] = {.fun = unary, .txt = "swtof", .letter = 'd'}, - [ASSWTOS] = {.fun = unary, .txt = "swtof", .letter = 's'}, - [ASSLTOD] = {.fun = unary, .txt = "sltof", .letter = 'd'}, - [ASSLTOS] = {.fun = unary, .txt = "sltof", .letter = 's'}, - - [ASEXTS] = {.fun = unary, .txt = "exts", .letter = 'd'}, - [ASTRUNCD] = {.fun = unary, .txt = "truncd", .letter = 's'}, - - [ASBRANCH] = {.fun = branch}, - [ASJMP] = {.fun = jmp}, - [ASRET] = {.fun = ret}, - [ASCALL] = {.fun = call}, - [ASCALLE] = {.fun = ecall, .txt = ")"}, - [ASCALLEX] = {.fun = ecall, .txt = ", ...)"}, - [ASPAR] = {.fun = param, .txt = "%s %s, "}, - [ASPARE] = {.fun = param, .txt = "%s %s"}, - [ASALLOC] = {.fun = asalloc}, - [ASFORM] = {.fun = form2local}, - - [ASVSTAR] = {.fun = vastart}, - [ASVARG] = {.fun = vaarg}, -}; - -static char buff[ADDR_LEN]; -/* - * : is for user-defined Aggregate Types - * $ is for globals (represented by a pointer) - * % is for function-scope temporaries - * @ is for block labels - */ -static char -sigil(Symbol *sym) -{ - switch (sym->kind) { - case SEXTRN: - case SGLOB: - case SPRIV: - case SLOCAL: - return '$'; - case SAUTO: - case STMP: - return '%'; - case SLABEL: - return '@'; - default: - abort(); - } -} - -static char * -symname(Symbol *sym) -{ - char c = sigil(sym); - - if (sym->name) { - switch (sym->kind) { - case SEXTRN: - case SGLOB: - sprintf(buff, "%c%s", c, sym->name); - return buff; - case SLOCAL: - case SPRIV: - case SAUTO: - sprintf(buff, "%c%s.%u", c, sym->name, sym->id); - return buff; - default: - abort(); - } - } - sprintf(buff, "%c.%u", c, sym->numid); - - return buff; -} - -static void -emitconst(Node *np) -{ - switch (np->type.size) { - case 1: - printf("%d", (int) np->u.i & 0xFF); - break; - case 2: - printf("%d", (int) np->u.i & 0xFFFF); - break; - case 4: - printf("%ld", (long) np->u.i & 0xFFFFFFFF); - break; - case 8: - printf("%lld", (long long) np->u.i); - break; - default: - abort(); - } -} - -static void -emittree(Node *np) -{ - if (!np) - return; - - switch (np->op) { - case OSTRING: - printf("\"%s\"", np->u.s); - free(np->u.s); - np->u.s = NULL; - break; - case OCONST: - emitconst(np); - break; - case OADDR: - emittree(np->left); - break; - case OMEM: - fputs(symname(np->u.sym), stdout); - break; - default: - emittree(np->left); - printf(" %c ", np->op); - emittree(np->right); - break; - } -} - -static char * -size2asm(Type *tp) -{ - if (tp->flags & STRF) { - return "b"; - } else if (tp->flags & INTF) { - switch (tp->size) { - case 1: - return "b"; - case 2: - return "h"; - case 4: - return "w"; - case 8: - return "l"; - } - } else if (tp->flags & FLOATF) { - if (tp->size == 4) - return "s"; - else if (tp->size == 8) - return "d"; - } - abort(); -} - -void -defglobal(Symbol *sym) -{ - if (sym->kind == SEXTRN) - return; - if (sym->kind == SGLOB) - fputs("export ", stdout); - printf("data %s = {\n", symname(sym)); - if (sym->type.flags & INITF) - return; - printf("\tz\t%lu\n}\n", sym->type.size); -} - -void -defpar(Symbol *sym) -{ - sym->type.flags |= PARF; -} - -void -defvar(Symbol *sym) -{ - if (sym->kind == SREG) - sym->kind = SAUTO; -} - -void -data(Node *np) -{ - printf("\t%s\t", size2asm(&np->type)); - emittree(np); - putchar(','); - putchar('\n'); -} - -static char * -size2stack(Type *tp) -{ - if (tp->flags & INTF) { - switch (tp->size) { - case 1: - case 2: - case 4: - return "w"; - case 8: - return "l"; - } - } else if (tp->flags & FLOATF) { - if (tp->size == 4) - return "s"; - else if (tp->size == 8) - return "d"; - } else if (tp->size == 0) { - return "w"; - } - abort(); -} - -void -writeout(void) -{ - Symbol *p; - Type *tp; - char *sep, *name; - int haslabel = 0; - - if (!curfun) - return; - if (curfun->kind == SGLOB) - fputs("export ", stdout); - printf("function %s %s(", size2stack(&curfun->rtype), symname(curfun)); - - /* declare formal parameters */ - for (sep = "", p = locals; p; p = p->next, sep = ",") { - if ((p->type.flags & PARF) == 0) - break; - printf("%s%s %s.val", sep, size2stack(&p->type), symname(p)); - } - printf("%s)\n{\n", (curfun->type.flags&ELLIPS) ? ", ..." : ""); - - /* emit assembler instructions */ - for (pc = prog; pc; pc = pc->next) { - if (pc->label) { - haslabel = 1; - printf("%s\n", symname(pc->label)); - } - if (!pc->op) - continue; - if (pc->flags&BBENTRY && !haslabel) - printf("%s\n", symname(newlabel())); - (*optbl[pc->op].fun)(); - if (!pc->label) - haslabel = 0; - } - - puts("}"); -} - -static char * -addr2txt(Addr *a) -{ - switch (a->kind) { - case SCONST: - sprintf(buff, "%llu", (unsigned long long) a->u.i); - return buff; - case SAUTO: - case SLABEL: - case STMP: - case SGLOB: - case SEXTRN: - case SPRIV: - case SLOCAL: - return symname(a->u.sym); - default: - abort(); - } -} - -static void -binary(void) -{ - struct opdata *p = &optbl[pc->op]; - char to[ADDR_LEN], from1[ADDR_LEN], from2[ADDR_LEN]; - - strcpy(to, addr2txt(&pc->to)); - strcpy(from1, addr2txt(&pc->from1)); - strcpy(from2, addr2txt(&pc->from2)); - printf("\t%s =%c\t%s\t%s,%s\n", to, p->letter, p->txt, from1, from2); -} - -static void -ldir(void) -{ - struct opdata *p = &optbl[pc->op]; - char to[ADDR_LEN], from[ADDR_LEN]; - /* TODO: what type do we use for the size? */ - - /* TODO: it is pending */ -} - -static void -store(void) -{ - struct opdata *p = &optbl[pc->op]; - char to[ADDR_LEN], from[ADDR_LEN]; - - strcpy(to, addr2txt(&pc->to)); - strcpy(from, addr2txt(&pc->from1)); - printf("\t\t%s%c\t%s,%s\n", p->txt, p->letter, from, to); -} - -static void -unary(void) -{ - struct opdata *p = &optbl[pc->op]; - char to[ADDR_LEN], from[ADDR_LEN]; - - strcpy(to, addr2txt(&pc->to)); - strcpy(from, addr2txt(&pc->from1)); - printf("\t%s =%c\t%s\t%s\n", to, p->letter, p->txt, from); -} - -static void -call(void) -{ - struct opdata *p = &optbl[pc->op]; - char to[ADDR_LEN], from[ADDR_LEN]; - Symbol *sym = pc->to.u.sym; - - strcpy(to, addr2txt(&pc->to)); - strcpy(from, addr2txt(&pc->from1)); - printf("\t%s =%s\tcall\t%s(", - to, size2stack(&sym->type), from); -} - -static void -param(void) -{ - Symbol *sym = pc->from2.u.sym; - - printf(optbl[pc->op].txt, - size2stack(&sym->type), addr2txt(&pc->from1)); -} - -static void -ecall(void) -{ - struct opdata *p = &optbl[pc->op]; - - puts(p->txt); -} - -static void -ret(void) -{ - if (pc->from1.kind == SNONE) - puts("\t\tret"); - else - printf("\t\tret\t%s\n", addr2txt(&pc->from1)); -} - -static void -jmp(void) -{ - printf("\t\tjmp\t%s\n", addr2txt(&pc->from1)); -} - -static void -branch(void) -{ - char to[ADDR_LEN], from1[ADDR_LEN], from2[ADDR_LEN]; - - strcpy(to, addr2txt(&pc->to)); - strcpy(from1, addr2txt(&pc->from1)); - strcpy(from2, addr2txt(&pc->from2)); - printf("\t\tjnz\t%s,%s,%s\n", to, from1, from2); -} - -static void -vastart(void) -{ - printf("\t\tvastart %s\n", addr2txt(&pc->from1)); -} - -static void -vaarg(void) -{ - Symbol *sym = pc->to.u.sym; - Type *tp = &sym->type; - char to[ADDR_LEN], from[ADDR_LEN]; - - strcpy(to, addr2txt(&pc->to)); - strcpy(from, addr2txt(&pc->from1)); - printf("\t\t%s =%s vaarg %s\n", to, size2asm(tp), from); -} - -static void -asalloc(void) -{ - Symbol *sym = pc->to.u.sym; - Type *tp = &sym->type; - extern Type ptrtype; - - printf("\t%s =%s\talloc%lu\t%lu\n", - symname(sym), size2asm(&ptrtype), tp->align+3 & ~3, tp->size); -} - -static void -form2local(void) -{ - Symbol *sym = pc->to.u.sym; - Type *tp = &sym->type; - char *name = symname(sym); - - printf("\t\tstore%s\t%s.val,%s\n", size2asm(tp), name, name); -} - -void -endinit(void) -{ - puts("}"); -} - -void -getbblocks(void) -{ - Inst *i; - - if (!prog) - return; - - prog->flags |= BBENTRY; - for (pc = prog; pc; pc = pc->next) { - switch (pc->op) { - case ASBRANCH: - i = pc->from2.u.sym->u.inst; - i->flags |= BBENTRY; - case ASJMP: - i = pc->from1.u.sym->u.inst; - i->flags |= BBENTRY; - case ASRET: - if (pc->next) - pc->next->flags |= BBENTRY; - break; - } - } -} diff --git a/cc2/target/qbe/optm.c b/cc2/target/qbe/optm.c @@ -1,57 +0,0 @@ -static char sccsid[] = "@(#) ./cc2/arch/qbe/optm.c"; - -#include <stddef.h> - -#include "../../../inc/scc.h" -#include "../../cc2.h" - -Node * -optm_dep(Node *np) -{ - int op = np->op; - Node *p, *dst, *next = np->next; - Symbol *sym, *osym; - - switch (op) { - case OEFUN: - /* - * In QBE we need at the end of a basic block - * a jump, so we have to ensure that the last - * statement of the function is a ret, a jmp - * or a branch. In the same way, QBE does - * not accept labels at the end of a function - * (ONOP is used for labels) so we have to add - * a ret there, and in the case of branches - * we need a label for the next statement - */ - op = (np->prev) ? np->prev->op : 0; - if (!op || op == ONOP || op == OBRANCH || (op != ORET && op != OJMP)) - addstmt(node(ORET), KEEPCUR); - break; - case OBRANCH: - if (!next->label) { - sym = getsym(TMPSYM); - sym->kind = SLABEL; - next->label = sym; - } - case OJMP: - for (;;) { - dst = np->u.sym->u.stmt; - if (dst->op != OJMP) - break; - np->u.sym = dst->u.sym; - } - for (p = np->next; p; p = p->next) { - if (p == dst) - return NULL; - if (p->op == ONOP || - p->op == OBLOOP || - p->op == OELOOP) { - continue; - } - break; - } - break; - } - return np; -} diff --git a/cc2/target/qbe_amd64-sysv/target.mk b/cc2/target/qbe_amd64-sysv/target.mk @@ -1,9 +0,0 @@ - -OBJ-qbe_amd64-sysv = $(OBJ) \ - target/qbe/cgen.o \ - target/qbe/optm.o \ - target/qbe/code.o \ - target/amd64-sysv/types.o - -$(LIBEXEC)/cc2-qbe_amd64-sysv: $(OBJ-qbe_amd64-sysv) - $(CC) $(SCC_LDFLAGS) $(OBJ-qbe_amd64-sysv) -lscc -o $@ diff --git a/cc2/target/qbe_arm64-sysv/target.mk b/cc2/target/qbe_arm64-sysv/target.mk @@ -1,5 +0,0 @@ -OBJ-qbe_arm64-sysv = $(OBJ) \ - target/qbe/cgen.o \ - target/qbe/optm.o \ - target/qbe/code.o \ - target/arm64-sysv/types.o diff --git a/cc2/target/z80-scc/cgen.c b/cc2/target/z80-scc/cgen.c @@ -1,160 +0,0 @@ -static char sccsid[] = "@(#) ./cc2/arch/z80/cgen.c"; - -#include <stdlib.h> - -#include "arch.h" -#include "../../../inc/scc.h" -#include "../../cc2.h" - -static void -swtch(Node *idx) -{ -} - -static Node * -rhs(Node *np, Node *ret) -{ -} - -static Node * -field(Node *np, Node *ret, int islhs) -{ -} - -static Node * -lhs(Node *np, Node *new) -{ - switch (np->op) { - case OMEM: - case OAUTO: - *new = *np; - return new; - case OPTR: - return rhs(np->left, new); - case OFIELD: - return field(np, new, 1); - default: - abort(); - } -} - -static void -bool(Node *np, Symbol *true, Symbol *false) -{ - Node *l = np->left, *r = np->right; - Node ret, ifyes, ifno; - Symbol *label; - - switch (np->op) { - case ONEG: - bool(l, false, true); - break; - case OAND: - label = newlabel(); - bool(l, label, false); - setlabel(label); - bool(r, true, false); - break; - case OOR: - label = newlabel(); - bool(l, true, label); - setlabel(label); - bool(r, true, false); - break; - default: - label2node(&ifyes, true); - label2node(&ifno, false); - code(ASBRANCH, rhs(np, &ret), &ifyes, &ifno); - break; - } -} - -Node * -cgen(Node *np) -{ - Node aux, *p, *next; - - setlabel(np->label); - switch (np->op) { - case OJMP: - label2node(&aux, np->u.sym); - code(ASJMP, NULL, &aux, NULL); - break; - case OBRANCH: - next = np->next; - if (!next->label) - next->label = newlabel(); - bool(np->left, np->u.sym, next->label); - break; - case ORET: - p = np->left; - if (p) - p = rhs(np->left, &aux); - code(ASRET, NULL, p, NULL); - break; - case OBSWITCH: - swtch(rhs(np->left, &aux)); - break; - default: - rhs(np, &aux); - break; - } - return NULL; -} - -/* - * This is strongly influenced by - * http://plan9.bell-labs.com/sys/doc/compiler.ps (/sys/doc/compiler.ps) - * calculate addresability as follows - * AUTO => 11 value+fp - * REG => 13 reg - * STATIC => 12 (value) - * CONST => 20 $value - */ -Node * -sethi(Node *np) -{ - Node *lp, *rp; - - if (!np) - return np; - - np->complex = 0; - np->address = 0; - lp = np->left; - rp = np->right; - switch (np->op) { - case OAUTO: - np->address = 11; - break; - case OREG: - np->address = 13; - break; - case OMEM: - np->address = 12; - break; - case OCONST: - np->address = 20; - break; - default: - sethi(lp); - sethi(rp); - break; - } - - if (np->address > 10) - return np; - if (lp) - np->complex = lp->complex; - if (rp) { - int d = np->complex - rp->complex; - - if (d == 0) - ++np->complex; - else if (d < 0) - np->complex = rp->complex; - } - if (np->complex == 0) - ++np->complex; - return np; -} diff --git a/cc2/target/z80-scc/code.c b/cc2/target/z80-scc/code.c @@ -1,228 +0,0 @@ -static char sccsid[] = "@(#) ./cc2/arch/z80/code.c"; - -#include <stdio.h> -#include <stdlib.h> - -#include <cstd.h> -#include "arch.h" -#include "../../../inc/scc.h" -#include "../../cc2.h" - -enum segment { - CODESEG, - DATASEG, - BSSSEG, - NOSEG -}; - -static int curseg = NOSEG; -static unsigned long offpar, offvar; - -static void -segment(int seg) -{ - static char *txt[] = { - [CODESEG] = "\tCSEG\n", - [DATASEG] = "\tDSEG\n", - [BSSSEG] = "\tASEG\n", - }; - - if (seg == curseg) - return; - fputs(txt[seg], stdout); - curseg = seg; -} - -static char * -symname(Symbol *sym) -{ - static char name[INTIDENTSIZ+1]; - - if (sym->name) { - switch (sym->kind) { - case SGLOB: - case SEXTRN: - snprintf(name, sizeof(name), "_%s", sym->name); - return name; - case SPRIV: - return sym->name; - } - } - - sprintf(name, ".%d", sym->numid); - - return name; -} - -static void -label(Symbol *sym) -{ - int seg; - char *name = symname(sym); - - if (sym->type.flags & FUNF) - seg = CODESEG; - else if (sym->type.flags & INITF) - seg = DATASEG; - else - seg = BSSSEG; - segment(seg); - - switch (sym->kind) { - case SEXTRN: - printf("\tEXTRN\t%s\n", name); - return; - case SGLOB: - printf("\tPUBLIC\t%s\n", name); - break; - } - - printf("%s:\n", name); -} - -static void -emitconst(Node *np) -{ - switch (np->type.size) { - case 1: - printf("%d", (int) np->u.i & 0xFF); - break; - case 2: - printf("%d", (int) np->u.i & 0xFFFF); - break; - case 4: - printf("%ld", (long) np->u.i & 0xFFFFFFFF); - break; - default: - abort(); - } -} - -static void -emittree(Node *np) -{ - if (!np) - return; - - switch (np->op) { - case OSTRING: - printf("\"%s\"", np->u.s); - free(np->u.s); - np->u.s = NULL; - break; - case OCONST: - emitconst(np); - break; - case OADDR: - emittree(np->left); - break; - case OMEM: - fputs(symname(np->u.sym), stdout); - break; - default: - emittree(np->left); - printf(" %c ", np->op); - emittree(np->right); - break; - } -} - -static void -size2asm(Type *tp) -{ - char *s; - - /* - * In z80 we can ignore the alignment - */ - if (tp->flags & STRF) { - s = "\tDB\t"; - } else { - switch (tp->size) { - case 1: - s = "\tDB\t"; - break; - case 2: - s = "\tDW\t"; - break; - case 4: - s = "\tDD\t"; - break; - default: - s = "\tDS\t%lu,"; - break; - } - } - printf(s, tp->size); -} - -void -newfun() -{ - offpar = offvar = 0; -} - -void -defpar(Symbol *sym) -{ - unsigned long align, size; - - if (sym->kind != SREG && sym->kind != SAUTO) - return; - align = sym->type.align; - size = sym->type.size; - - offpar -= align-1 & ~align; - sym->u.off = offpar; - offpar -= size; - sym->kind = SAUTO; -} - -void -defvar(Symbol *sym) -{ - unsigned long align, size; - - if (sym->kind != SREG && sym->kind != SAUTO) - return; - align = sym->type.align; - size = sym->type.size; - - offvar += align-1 & ~align; - sym->u.off = offvar; - offvar += size; - sym->kind = SAUTO; -} - -void -defglobal(Symbol *sym) -{ - label(sym); - if (sym->kind == SEXTRN || (sym->type.flags & INITF)) - return; - size2asm(&sym->type); - puts("0"); -} - -void -data(Node *np) -{ - size2asm(&np->type); - emittree(np); - putchar('\n'); -} - -void -writeout(void) -{ -} - -void -endinit(void) -{ -} - -void -getbblocks(void) -{ -} diff --git a/cc2/target/z80-scc/optm.c b/cc2/target/z80-scc/optm.c @@ -1,10 +0,0 @@ -static char sccsid[] = "@(#) ./cc2/arch/z80/optm.c"; - -#include "../../../inc/scc.h" -#include "../../cc2.h" - -Node * -optm_dep(Node *np) -{ - return np; -} diff --git a/cc2/target/z80-scc/target.mk b/cc2/target/z80-scc/target.mk @@ -1,9 +0,0 @@ - -OBJ-z80-scc = $(OBJ) \ - target/z80-scc/cgen.o \ - target/z80-scc/optm.o \ - target/z80-scc/code.o \ - target/z80-scc/types.o - -$(LIBEXEC)/cc2-z80-scc: $(OBJ-z80-scc) - $(CC) $(SCC_LDFLAGS) $(OBJ-z80-scc) -lscc -o $@ diff --git a/cc2/target/z80-scc/types.c b/cc2/target/z80-scc/types.c @@ -1,94 +0,0 @@ -static char sccsid[] = "@(#) ./cc2/arch/z80/types.c"; - -#include "../../../inc/scc.h" -#include "../../cc2.h" - - -Type int8type = { - .flags = SIGNF | INTF, - .size = 1, - .align = 1 -}; - -Type int16type = { - .flags = SIGNF | INTF, - .size = 2, - .align = 1 -}; - -Type int32type = { - .flags = SIGNF | INTF, - .size = 4, - .align = 1 -}; - -Type int64type = { - .flags = SIGNF | INTF, - .size = 8, - .align = 1 -}; - -Type uint8type = { - .flags = INTF, - .size = 1, - .align = 1 -}; - -Type uint16type = { - .flags = INTF, - .size = 2, - .align = 1 -}; - -Type uint32type = { - .flags = INTF, - .size = 4, - .align = 1 -}; - -Type uint64type = { - .flags = INTF, - .size = 8, - .align = 1 -}; - -Type ptrtype = { - .flags = INTF, - .size = 2, - .align = 1 -}; - -Type booltype = { - .flags = INTF, - .size = 1, - .align = 1 -}; - -Type float32type = { - .flags = FLOATF, - .size = 4, - .align = 1 -}; - -Type float64type = { - .flags = FLOATF, - .size = 4, - .align = 1 -}; - -Type float80type = { - .flags = FLOATF, - .size = 4, - .align = 1 -}; - -Type voidtype = { - .size = 0, - .align = 0 -}; - -/* this types is not going to be used in this arch */ -Type arg_type = { - .size = 0, - .align = 0 -}; diff --git a/config.mk b/config.mk @@ -1,30 +0,0 @@ -# scc version -VERSION = 0.1 - -## Customize below to fit your system -DRIVER = posix - -# Can be c89 or c99 -STD = c99 - -# paths -PREFIX = $(PWD)/$(PROJECTDIR)/root -MANPREFIX = $(PREFIX)/share/man - -# scc expects to be built by a C99 compiler -# if your system is not at least POSIX 2004 compatible, adjust CC -# CC = c99 -# AR = ar -AS = as - -### Systems -# Plan9 -#SYSCFLAGS = -D_SUSV2_SOURCE -#SYSLDCFLAGS = -#STDCFLAGS = -### -# BSD -#SYSCFLAGS = -#SYSLDCFLAGS = -#STDCFLAGS = -D_ISOC99_SOURCE -D_ANSI_SOURCE -### diff --git a/config.sh b/config.sh @@ -1,16 +0,0 @@ -#!/bin/sh - -case `uname` in -*BSD) - sys=BSD - ;; -*Plan9) - sys=Plan9 - ;; -*) - exit - ;; -esac - - -(echo '/^# '$sys'/+;/^###$/- s/^#//'; echo w) | ed -s config.mk diff --git a/config/amd64-linux.mk b/config/amd64-linux.mk @@ -0,0 +1,8 @@ +ARCH = amd64 +SYS = linux +ABI = amd64-posix +DRIVER = posix +STD = c99 +PREFIX = $(PWD)/$(PROJECTDIR)/root +MANPREFIX = $(PREFIX)/share/man +AS = as diff --git a/config/i386-linux.mk b/config/i386-linux.mk @@ -0,0 +1,5 @@ +DRIVER = posix +STD = c99 +PREFIX = $(PWD)/$(PROJECTDIR)/root +MANPREFIX = $(PREFIX)/share/man +AS = as diff --git a/driver/Makefile b/driver/Makefile @@ -1,10 +0,0 @@ -.POSIX: - -PROJECTDIR = .. -# fallback case if DRIVER isn't defined -DRIVER = posix - -include $(PROJECTDIR)/rules.mk - -all dep clean distclean: - +@cd $(DRIVER) && $(MAKE) $@ diff --git a/driver/posix/Makefile b/driver/posix/Makefile @@ -1,42 +0,0 @@ -.POSIX: - -PROJECTDIR = ../.. -include $(PROJECTDIR)/rules.mk -include $(LIBSCC)/libdep.mk -include $(INCLUDE)/incdep.mk - -# SYSLST is a list of backend-arch-abi-sys. First -# element of the list becomes the default target - -SYSLST = amd64-sysv-linux-elf z80-scc-none-none \ - i386-sysv-linux-elf amd64-sysv-openbsd-elf - -STDCFLAGS = - -TARGETS = $(BINDIR)/scc $(BINDIR)/scpp - -all: $(TARGETS) - -$(BINDIR)/scc: scc.o $(LIBDIR)/libscc.a - $(CC) $(SCC_LDFLAGS) scc.o -lscc -o $@ - -$(BINDIR)/scpp: cpp.sh config.h - set -x ;\ - trap "rm -f $$$$.sh" 0 2 3;\ - rm -f $@ ;\ - sed "s%@PREFIX@%$(PREFIX)%" < cpp.sh > $$$$.sh && \ - chmod +x $$$$.sh && \ - mv $$$$.sh $@ - -config.h: - PREFIX=$(PREFIX) ./config.sh $(SYSLST) - -dep: - $(PROJECTDIR)/mkdep.sh - -clean: - rm -f scc scpp *.o - rm -f $(TARGETS) - rm -f config.h - -include deps.mk diff --git a/inc/Makefile b/inc/Makefile @@ -1,37 +0,0 @@ -.POSIX: - -PROJECTDIR = .. - -include $(PROJECTDIR)/rules.mk -include inclst.mk - -all: config - -config: $(SYSHDR) - -$(INCLUDE)/ldflags.h: - rm -f $@ ; \ - trap "rm -f $$$$.h" 0 2 3; \ - cat < ldflags.def.h > $$$$.h; \ - mv $$$$.h $@ - -$(INCLUDE)/syscrts.h: - rm -f $@ ; \ - trap "rm -f $$$$.h" 0 2 3; \ - sed 's,PREFIX,"$(PREFIX)",g' < syscrts.def.h > $$$$.h && \ - mv $$$$.h $@ - -$(INCLUDE)/sysincludes.h: - rm -f $@ ; \ - trap "rm -f $$$$.h" 0 2 3; \ - sed 's,PREFIX,"$(PREFIX)",g' < sysincludes.def.h > $$$$.h && \ - mv $$$$.h $@ - -$(INCLUDE)/syslibs.h: - rm -f $@ ; \ - trap "rm -f $$$$.h" 0 2 3; \ - sed 's,PREFIX,"$(PREFIX)",g' < syslibs.def.h > $$$$.h && \ - mv $$$$.h $@ - -distclean: - rm -f $(SYSHDR) diff --git a/inc/incdep.mk b/inc/incdep.mk @@ -1,7 +0,0 @@ -include $(INCLUDE)/inclst.mk - -debug: - echo $(SYSHDR) - -$(SYSHDR): - +@cd $(INCLUDE) && $(MAKE) diff --git a/inc/inclst.mk b/inc/inclst.mk @@ -1,4 +0,0 @@ -SYSHDR = $(INCLUDE)/ldflags.h\ - $(INCLUDE)/syscrts.h\ - $(INCLUDE)/sysincludes.h\ - $(INCLUDE)/syslibs.h diff --git a/include/assert.h b/include/assert.h @@ -0,0 +1,8 @@ +extern void __assert(char *exp, char *file, long line); + +#undef assert +#ifndef NDEBUG +# define assert(exp) ((exp) ? (void) 0 : __assert(#exp, __FILE__, __LINE__)) +#else +# define assert(exp) ((void)0) +#endif diff --git a/include/bits/.gitignore b/include/bits/.gitignore @@ -0,0 +1 @@ +errno.h diff --git a/include/bits/amd64/arch/limits.h b/include/bits/amd64/arch/limits.h @@ -0,0 +1,18 @@ +#define CHAR_BIT 8 +#define SCHAR_MAX 0x7F +#define SCHAR_MIN (-SCHAR_MIN-1) +#define CHAR_MAX 0x7F +#define CHAR_MIN (-CHAR_MAX-1) +#define UCHAR_MAX 0xFF +#define SHRT_MAX 0x7FFF +#define SHRT_MIN (-SHRT_MAX-1) +#define USHRT_MAX 0xFFFF +#define INT_MAX 0x7FFFFFFF +#define INT_MIN (-INT_MAX-1) +#define UINT_MAX 0xFFFFFFFF +#define LONG_MAX 0x7FFFFFFFFFFFFFFF +#define LONG_MIN (-LONG_MAX-1) +#define ULONG_MAX 0xFFFFFFFFFFFFFFFF +#define LLONG_MAX 0x7FFFFFFFFFFFFFFF +#define LLONG_MIN (-LLONG_MAX-1) +#define ULLONG_MAX 0xFFFFFFFFFFFFFFFF diff --git a/include/bits/amd64/arch/setjmp.h b/include/bits/amd64/arch/setjmp.h @@ -0,0 +1 @@ +typedef unsigned long long jmp_buf[8]; diff --git a/include/bits/amd64/arch/stddef.h b/include/bits/amd64/arch/stddef.h @@ -0,0 +1,14 @@ +#ifndef _SIZET +typedef unsigned long size_t; +#define _SIZET +#endif + +#ifndef _WCHAR_T +typedef int wchar_t; +#define _WCHAR_T +#endif + +#ifndef _PTRDIFF_T +typedef long ptrdiff_t; +#define _PTRDIFF_T +#endif diff --git a/include/bits/amd64/arch/stdint.h b/include/bits/amd64/arch/stdint.h @@ -0,0 +1,102 @@ +#define INT8_MAX 0x7F +#define INT8_MIN (-INT8_MAX-1) +#define UINT8_MAX 0xFF + +#define INT16_MAX 0x7FFF +#define INT16_MIN (-INT16_MAX-1) +#define UINT16_MAX 0xFFFF + +#define INT32_MAX 0x7FFFFFFF +#define INT32_MIN (-INT32_MAX-1) +#define UINT32_MAX 0xFFFFFFFF + +#define INT64_MAX 0x7FFFFFFFFFFFFFFF +#define INT64_MIN (-INT64_MAX-1) +#define UINT64_MAX 0xFFFFFFFFFFFFFFFF + +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST8_MAX INT8_MAX +#define UINT_LEAST8_MAX UINT8_MAX + +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST16_MAX INT16_MAX +#define UINT_LEAST16_MAX UINT16_MAX + +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST32_MAX INT32_MAX +#define UINT_LEAST32_MAX UINT32_MAX + +#define INT_LEAST64_MIN INT64_MIN +#define INT_LEAST64_MAX INT64_MAX +#define UINT_LEAST64_MAX UINT64_MAX + +#define INT_FAST8_MIN INT32_MIN +#define INT_FAST8_MAX INT32_MAX +#define UINT_FAST8_MAX UINT32_MAX + +#define INT_FAST16_MIN INT32_MIN +#define INT_FAST16_MAX INT32_MAX +#define UINT_FAST16_MAX UINT32_MAX + +#define INT_FAST32_MIN INT32_MIN +#define INT_FAST32_MAX INT32_MAX +#define UINT_FAST32_MAX UINT32_MAX + +#define INT_FAST64_MIN INT64_MIN +#define INT_FAST64_MAX INT64_MAX +#define UINT_FAST64_MAX UINT64_MAX + +#define INTPTR_MIN INT64_MIN +#define INTPTR_MAX INT64_MAX +#define UINTPTR_MAX UINT64_MAX + +#define INTMAX_MIN INT64_MIN +#define INTMAX_MAX INT64_MAX +#define UINTMAX_MAX UINT64_MAX + +#define PTRDIFF_MIN INT64_MIN +#define PTRDIFF_MAX INT64_MAX + +#define SIG_ATOMIC_MIN INT32_MIN +#define SIG_ATOMIC_MAX INT32_MAX + +#define SIZE_MAX UINT64_MAX + +#define WCHAR_MIN INT32_MIN +#define WCHAR_MAX INT32_MAX + +typedef signed char int8_t; +typedef short int16_t; +typedef int int32_t; +typedef long int64_t; + +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned uint32_t; +typedef unsigned long uint64_t; + +typedef signed char int8_least_t; +typedef short int16_least_t; +typedef int int32_least_t; +typedef long int64_least_t; + +typedef unsigned char uint8_least_t; +typedef unsigned short uint16_least_t; +typedef unsigned uint32_least_t; +typedef unsigned long uint64_least_t; + +typedef int int8_fast_t; +typedef int int16_fast_t; +typedef int int32_fast_t; +typedef long int64_fast_t; + +typedef unsigned uint8_fast_t; +typedef unsigned uint16_fast_t; +typedef unsigned uint32_fast_t; +typedef unsigned long uint64_fast_t; + +typedef long intptr_t; +typedef unsigned long uintptr_t; + +typedef long intmax_t; +typedef unsigned long uintmax_t; diff --git a/include/bits/amd64/arch/stdio.h b/include/bits/amd64/arch/stdio.h @@ -0,0 +1,15 @@ +#ifndef _SIZET +typedef unsigned long size_t; +#define _SIZET +#endif + +#define BUFSIZ 512 +#define FILENAME_MAX 256 +#define FOPEN_MAX 16 + +#define TMP_MAX 25 +#define L_tmpnam 256 + +#define _TMPNAME "/tmp/tmp.0000000" + +typedef int fpos_t; diff --git a/include/bits/amd64/arch/stdlib.h b/include/bits/amd64/arch/stdlib.h @@ -0,0 +1,14 @@ +#ifndef _SIZET +typedef unsigned long size_t; +#define _SIZET +#endif + +#define EXIT_FAILURE 1 +#define EXIT_SUCCESS 0 + +#ifndef _WCHAR_T +typedef int wchar_t; +#define _WCHAR_T +#endif + +#define _ALIGNTYPE long double diff --git a/include/bits/amd64/arch/string.h b/include/bits/amd64/arch/string.h @@ -0,0 +1,5 @@ +#ifndef _SIZET +typedef unsigned long size_t; +#endif + +#define __NUMCHARS 128 +\ No newline at end of file diff --git a/include/bits/amd64/arch/time.h b/include/bits/amd64/arch/time.h @@ -0,0 +1,8 @@ +#ifndef _SIZET +typedef unsigned long size_t; +#define _SIZET +#endif + +#define _MAXYEAR 9999 + +typedef long int time_t; diff --git a/include/bits/arm32/arch/limits.h b/include/bits/arm32/arch/limits.h @@ -0,0 +1,18 @@ +#define CHAR_BIT 8 +#define SCHAR_MAX 0x7F +#define SCHAR_MIN (-SCHAR_MIN - 1) +#define CHAR_MAX 0x7F +#define CHAR_MIN (-CHAR_MAX - 1) +#define UCHAR_MAX 0xFF +#define SHRT_MAX 0x7FFF +#define SHRT_MIN (-SHRT_MAX - 1) +#define USHRT_MAX 0xFFFF +#define INT_MAX 0x7FFFFFFF +#define INT_MIN (-INT_MAX - 1) +#define UINT_MAX 0xFFFFFFFF +#define LONG_MAX 0x7FFFFFFF +#define LONG_MIN (-LONG_MAX - 1) +#define ULONG_MAX 0xFFFFFFFF +#define LLONG_MAX 0x7FFFFFFFFFFFFFFF +#define LLONG_MIN (-LLONG_MAX - 1) +#define ULLONG_MAX 0xFFFFFFFFFFFFFFFF diff --git a/include/bits/arm32/arch/setjmp.h b/include/bits/arm32/arch/setjmp.h @@ -0,0 +1 @@ +typedef unsigned long jmp_buf[10]; diff --git a/include/bits/arm32/arch/stddef.h b/include/bits/arm32/arch/stddef.h @@ -0,0 +1,9 @@ +#ifndef SIZET_ +typedef unsigned int size_t; +#define SIZET_ +#endif + +#ifndef _PTRDIFF_T +typedef long ptrdiff_t; +#define _PTRDIFF_T +#endif diff --git a/include/bits/arm32/arch/stdint.h b/include/bits/arm32/arch/stdint.h @@ -0,0 +1,96 @@ +#define INT8_MAX 0x7F +#define INT8_MIN (-INT8_MAX - 1) +#define UINT8_MAX 0xFF + +#define INT16_MAX 0x7FFF +#define INT16_MIN (-INT16_MAX - 1) +#define UINT16_MAX 0xFFFF + +#define INT32_MAX 0x7FFFFFFF +#define INT32_MIN (-INT32_MAX - 1) +#define UINT32_MAX 0xFFFFFFFF + +#define INT64_MAX 0x7FFFFFFFFFFFFFFF +#define INT64_MIN (-INT64_MAX - 1) +#define UINT64_MAX 0xFFFFFFFFFFFFFFFF + +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST8_MAX INT8_MAX +#define UINT_LEAST8_MAX UINT8_MAX + +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST16_MAX INT16_MAX +#define UINT_LEAST16_MAX UINT16_MAX + +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST32_MAX INT32_MAX +#define UINT_LEAST32_MAX UINT32_MAX + +#define INT_LEAST64_MIN INT64_MIN +#define INT_LEAST64_MAX INT64_MAX +#define UINT_LEAST64_MAX UINT64_MAX + +#define INT_FAST8_MIN INT32_MIN +#define INT_FAST8_MAX INT32_MAX +#define UINT_FAST8_MAX UINT32_MAX + +#define INT_FAST16_MIN INT32_MIN +#define INT_FAST16_MAX INT32_MAX +#define UINT_FAST16_MAX UINT32_MAX + +#define INT_FAST32_MIN INT32_MIN +#define INT_FAST32_MAX INT32_MAX +#define UINT_FAST32_MAX UINT32_MAX + +#define INT_FAST64_MIN INT64_MIN +#define INT_FAST64_MAX INT64_MAX +#define UINT_FAST64_MAX UINT64_MAX + +#define INTPTR_MIN INT32_MIN +#define INTPTR_MAX INT32_MAX +#define UINTPTR_MAX UINT32_MAX + +#define INTMAX_MIN INT64_MIN +#define INTMAX_MAX INT64_MAX +#define UINTMAX_MAX UINT64_MAX + +#define PTRDIFF_MIN INT32_MIN +#define PTRDIFF_MAX INT32_MAX + +#define SIZE_MAX UINT32_MAX + +typedef signed char int8_t; +typedef short int16_t; +typedef int int32_t; +typedef long long int64_t; + +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; +typedef unsigned long long uint64_t; + +typedef signed char int8_least_t; +typedef short int16_least_t; +typedef int int32_least_t; +typedef long long int64_least_t; + +typedef unsigned char uint8_least_t; +typedef unsigned short uint16_least_t; +typedef unsigned int uint32_least_t; +typedef unsigned long long uint64_least_t; + +typedef int int8_fast_t; +typedef int int16_fast_t; +typedef int int32_fast_t; +typedef long long int64_fast_t; + +typedef unsigned int uint8_fast_t; +typedef unsigned int uint16_fast_t; +typedef unsigned int uint32_fast_t; +typedef unsigned long long uint64_fast_t; + +typedef long intptr_t; +typedef unsigned long uintptr_t; + +typedef long long intmax_t; +typedef unsigned long long uintmax_t; diff --git a/include/bits/arm32/arch/stdio.h b/include/bits/arm32/arch/stdio.h @@ -0,0 +1,15 @@ +#ifndef _SIZET +typedef unsigned int size_t; +#define _SIZET +#endif + +#define BUFSIZ 512 +#define FILENAME_MAX 256 +#define FOPEN_MAX 16 + +#define TMP_MAX 25 +#define L_tmpnam 256 + +#define _TMPNAME "/tmp/tmp.0000000" + +typedef int fpos_t; diff --git a/include/bits/arm32/arch/stdlib.h b/include/bits/arm32/arch/stdlib.h @@ -0,0 +1,14 @@ +#ifndef SIZET_ +typedef unsigned int size_t; +#define SIZET_ +#endif + +#define EXIT_FAILURE 1 +#define EXIT_SUCCESS 0 + +#ifndef _WCHAR_T +typedef int wchar_t; // TODO +#define _WCHAR_T +#endif + +#define _ALIGNTYPE long double diff --git a/include/bits/arm32/arch/string.h b/include/bits/arm32/arch/string.h @@ -0,0 +1,6 @@ +#ifndef SIZET_ +typedef unsigned int size_t; +#define SIZET_ +#endif + +#define __NUMCHARS 128 diff --git a/include/bits/arm32/arch/time.h b/include/bits/arm32/arch/time.h @@ -0,0 +1,8 @@ +#ifndef _SIZET +typedef unsigned int size_t; +#define _SIZET +#endif + +#define _MAXYEAR 9999 + +typedef long int time_t; diff --git a/include/bits/arm64/arch/limits.h b/include/bits/arm64/arch/limits.h @@ -0,0 +1,18 @@ +#define CHAR_BIT 8 +#define SCHAR_MAX 0x7F +#define SCHAR_MIN (-SCHAR_MIN - 1) +#define CHAR_MAX 0x7F +#define CHAR_MIN (-CHAR_MAX - 1) +#define UCHAR_MAX 0xFF +#define SHRT_MAX 0x7FFF +#define SHRT_MIN (-SHRT_MAX - 1) +#define USHRT_MAX 0xFFFF +#define INT_MAX 0x7FFFFFFF +#define INT_MIN (-INT_MAX - 1) +#define UINT_MAX 0xFFFFFFFF +#define LONG_MAX 0x7FFFFFFFFFFFFFFF +#define LONG_MIN (-LONG_MAX - 1) +#define ULONG_MAX 0xFFFFFFFFFFFFFFFF +#define LLONG_MAX 0x7FFFFFFFFFFFFFFF +#define LLONG_MIN (-LLONG_MAX - 1) +#define ULLONG_MAX 0xFFFFFFFFFFFFFFFF diff --git a/include/bits/arm64/arch/setjmp.h b/include/bits/arm64/arch/setjmp.h @@ -0,0 +1 @@ +typedef unsigned long long jmp_buf[22]; diff --git a/include/bits/arm64/arch/stddef.h b/include/bits/arm64/arch/stddef.h @@ -0,0 +1,9 @@ +#ifndef SIZET_ +typedef unsigned long size_t; +#define SIZET_ +#endif + +#ifndef _PTRDIFF_T +typedef long ptrdiff_t; +#define _PTRDIFF_T +#endif diff --git a/include/bits/arm64/arch/stdint.h b/include/bits/arm64/arch/stdint.h @@ -0,0 +1,96 @@ +#define INT8_MAX 0x7F +#define INT8_MIN (-INT8_MAX - 1) +#define UINT8_MAX 0xFFU + +#define INT16_MAX 0x7FFF +#define INT16_MIN (-INT16_MAX - 1) +#define UINT16_MAX 0xFFFFU + +#define INT32_MAX 0x7FFFFFFF +#define INT32_MIN (-INT32_MAX - 1) +#define UINT32_MAX 0xFFFFFFFF + +#define INT64_MAX 0x7FFFFFFFFFFFFFFF +#define INT64_MIN (-INT64_MAX - 1) +#define UINT64_MAX 0xFFFFFFFFFFFFFFFF + +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST8_MAX INT8_MAX +#define UINT_LEAST8_MAX UINT8_MAX + +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST16_MAX INT16_MAX +#define UINT_LEAST16_MAX UINT16_MAX + +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST32_MAX INT32_MAX +#define UINT_LEAST32_MAX UINT32_MAX + +#define INT_LEAST64_MIN INT64_MIN +#define INT_LEAST64_MAX INT64_MAX +#define UINT_LEAST64_MAX UINT64_MAX + +#define INT_FAST8_MIN INT32_MIN +#define INT_FAST8_MAX INT32_MAX +#define UINT_FAST8_MAX UINT32_MAX + +#define INT_FAST16_MIN INT32_MIN +#define INT_FAST16_MAX INT32_MAX +#define UINT_FAST16_MAX UINT32_MAX + +#define INT_FAST32_MIN INT32_MIN +#define INT_FAST32_MAX INT32_MAX +#define UINT_FAST32_MAX UINT32_MAX + +#define INT_FAST64_MIN INT64_MIN +#define INT_FAST64_MAX INT64_MAX +#define UINT_FAST64_MAX UINT64_MAX + +#define INTPTR_MIN INT64_MIN +#define INTPTR_MAX INT64_MAX +#define UINTPTR_MAX UINT64_MAX + +#define INTMAX_MIN INT64_MIN +#define INTMAX_MAX INT64_MAX +#define UINTMAX_MAX UINT64_MAX + +#define PTRDIFF_MIN INT64_MIN +#define PTRDIFF_MAX INT64_MAX + +#define SIZE_MAX UINT64_MAX + +typedef signed char int8_t; +typedef short int16_t; +typedef int int32_t; +typedef long long int64_t; + +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; +typedef unsigned long long uint64_t; + +typedef signed char int8_least_t; +typedef short int16_least_t; +typedef int int32_least_t; +typedef long long int64_least_t; + +typedef unsigned char uint8_least_t; +typedef unsigned short uint16_least_t; +typedef unsigned int uint32_least_t; +typedef unsigned long long uint64_least_t; + +typedef int int8_fast_t; +typedef int int16_fast_t; +typedef int int32_fast_t; +typedef long long int64_fast_t; + +typedef unsigned int uint8_fast_t; +typedef unsigned int uint16_fast_t; +typedef unsigned int uint32_fast_t; +typedef unsigned long long uint64_fast_t; + +typedef long intptr_t; +typedef unsigned long uintptr_t; + +typedef long intmax_t; +typedef unsigned long uintmax_t; diff --git a/include/bits/arm64/arch/stdio.h b/include/bits/arm64/arch/stdio.h @@ -0,0 +1,15 @@ +#ifndef _SIZET +typedef unsigned long size_t; +#define _SIZET +#endif + +#define BUFSIZ 512 +#define FILENAME_MAX 256 +#define FOPEN_MAX 16 + +#define TMP_MAX 25 +#define L_tmpnam 256 + +#define _TMPNAME "/tmp/tmp.0000000" + +typedef int fpos_t; diff --git a/include/bits/arm64/arch/stdlib.h b/include/bits/arm64/arch/stdlib.h @@ -0,0 +1,14 @@ +#ifndef SIZET_ +typedef unsigned long size_t; +#define SIZET_ +#endif + +#define EXIT_FAILURE 1 +#define EXIT_SUCCESS 0 + +#ifndef _WCHAR_T +typedef int wchar_t; +#define _WCHAR_T +#endif + +#define _ALIGNTYPE long double diff --git a/include/bits/arm64/arch/string.h b/include/bits/arm64/arch/string.h @@ -0,0 +1,6 @@ +#ifndef SIZET_ +typedef unsigned long size_t; +#define SIZET_ +#endif + +#define __NUMCHARS 128 diff --git a/include/bits/arm64/arch/time.h b/include/bits/arm64/arch/time.h @@ -0,0 +1,8 @@ +#ifndef _SIZET +typedef unsigned long size_t; +#define _SIZET +#endif + +#define _MAXYEAR 9999 + +typedef long int time_t; diff --git a/include/bits/dragonfly/sys.h b/include/bits/dragonfly/sys.h @@ -0,0 +1,19 @@ +#define O_RDONLY 0x00000000 +#define O_WRONLY 0x00000001 +#define O_RDWR 0x00000002 + +#define O_TRUNC 0x00000400 +#define O_APPEND 0x00000008 +#define O_CREAT 0x00000200 + +typedef int pid_t; + +struct sigaction { + void (*sa_handler)(int); + char sa_mask[8]; + int sa_flags; +}; + +extern pid_t _getpid(void); +extern int _kill(pid_t pid, int signum); +extern int _sigaction(int sig, struct sigaction *new, struct sigaction *old); diff --git a/include/bits/dragonfly/sys/signal.h b/include/bits/dragonfly/sys/signal.h @@ -0,0 +1,27 @@ +typedef int sig_atomic_t; + +#define SIG_ERR ((void (*)(int))-1) +#define SIG_DFL ((void (*)(int)) 0) +#define SIG_IGN ((void (*)(int)) 1) + +#define SIGHUP 1 +#define SIGINT 2 +#define SIGQUIT 3 +#define SIGILL 4 +#define SIGABRT 6 +#define SIGFPE 8 +#define SIGKILL 9 +#define SIGSEGV 11 +#define SIGPIPE 13 +#define SIGALRM 14 +#define SIGTERM 15 +#define SIGSTOP 17 +#define SIGTSTP 18 +#define SIGCONT 19 +#define SIGCHLD 20 +#define SIGTTIN 21 +#define SIGTTOU 22 +#define SIGUSR1 30 +#define SIGUSR2 31 + +#define __NR_SIGNALS 32 diff --git a/include/bits/i386/arch/limits.h b/include/bits/i386/arch/limits.h @@ -0,0 +1,18 @@ +#define CHAR_BIT 8 +#define SCHAR_MAX 0x7F +#define SCHAR_MIN (-SCHAR_MIN-1) +#define CHAR_MAX 0x7F +#define CHAR_MIN (-CHAR_MAX-1) +#define UCHAR_MAX 0xFF +#define SHRT_MAX 0x7FFF +#define SHRT_MIN (-SHRT_MAX-1) +#define USHRT_MAX 0xFFFF +#define INT_MAX 0x7FFFFFFF +#define INT_MIN (-INT_MAX-1) +#define UINT_MAX 0xFFFFFFFF +#define LONG_MAX 0x7FFFFFFF +#define LONG_MIN (-LONG_MAX-1) +#define ULONG_MAX 0xFFFFFFFF +#define LLONG_MAX 0x7FFFFFFFFFFFFFFF +#define LLONG_MIN (-LLONG_MAX-1) +#define ULLONG_MAX 0xFFFFFFFFFFFFFFFF diff --git a/include/bits/i386/arch/stddef.h b/include/bits/i386/arch/stddef.h @@ -0,0 +1,14 @@ +#ifndef _SIZET +typedef unsigned long size_t; +#define _SIZET +#endif + +#ifndef _WCHAR_T +typedef int wchar_t; +#define _WCHAR_T +#endif + +#ifndef _PTRDIFF_T +typedef long ptrdiff_t; +#define _PTRDIFF_T +#endif diff --git a/include/bits/i386/arch/stdint.h b/include/bits/i386/arch/stdint.h @@ -0,0 +1,115 @@ +#define INT8_MAX 0x7F +#define INT8_MIN (-INT8_MAX-1) +#define UINT8_MAX 0xFF + +#define INT16_MAX 0x7FFF +#define INT16_MIN (-INT16_MAX-1) +#define UINT16_MAX 0xFFFF + +#define INT32_MAX 0x7FFFFFFF +#define INT32_MIN (-INT32_MAX-1) +#define UINT32_MAX 0xFFFFFFFF + +#define INT64_MAX 0x7FFFFFFFFFFFFFFF +#define INT64_MIN (-INT64_MAX-1) +#define UINT64_MAX 0xFFFFFFFFFFFFFFFF + +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST8_MAX INT8_MAX +#define UINT_LEAST8_MAX UINT8_MAX + +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST16_MAX INT16_MAX +#define UINT_LEAST16_MAX UINT16_MAX + +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST32_MAX INT32_MAX +#define UINT_LEAST32_MAX UINT32_MAX + +#define INT_LEAST64_MIN INT64_MIN +#define INT_LEAST64_MAX INT64_MAX +#define UINT_LEAST64_MAX UINT64_MAX + +#define INT_FAST8_MIN INT32_MIN +#define INT_FAST8_MAX INT32_MAX +#define UINT_FAST8_MAX UINT32_MAX + +#define INT_FAST16_MIN INT32_MIN +#define INT_FAST16_MAX INT32_MAX +#define UINT_FAST16_MAX UINT32_MAX + +#define INT_FAST32_MIN INT32_MIN +#define INT_FAST32_MAX INT32_MAX +#define UINT_FAST32_MAX UINT32_MAX + +#define INT_FAST64_MIN INT64_MIN +#define INT_FAST64_MAX INT64_MAX +#define UINT_FAST64_MAX UINT64_MAX + +#define INTPTR_MIN INT32_MIN +#define INTPTR_MAX INT32_MAX +#define UINTPTR_MAX UINT32_MAX + +#define INTMAX_MIN INT64_MIN +#define INTMAX_MAX INT64_MAX +#define UINTMAX_MAX UINT64_MAX + +#define PTRDIFF_MIN INT32_MIN +#define PTRDIFF_MAX INT32_MAX + +#define SIG_ATOMIC_MIN INT32_MIN +#define SIG_ATOMIC_MAX INT32_MAX + +#define SIZE_MAX UINT32_MAX + +#define WCHAR_MIN INT32_MIN +#define WCHAR_MAX INT32_MAX + +#define INT8_C(x) x +#define INT16_C(x) x +#define INT32_C(x) x +#define INT64_C(x) x ## LL + +#define UINT8_C(x) x +#define UINT16_C(x) x +#define UINT32_C(x) x ## U +#define UINT64_C(x) x ## ULL + +#define INTMAX_C(x) x ## LL +#define UINTMAX_C(x) x ## ULL + +typedef signed char int8_t; +typedef short int16_t; +typedef int int32_t; +typedef long long int64_t; + +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned uint32_t; +typedef unsigned long long uint64_t; + +typedef signed char int8_least_t; +typedef short int16_least_t; +typedef int int32_least_t; +typedef long long int64_least_t; + +typedef unsigned char uint8_least_t; +typedef unsigned short uint16_least_t; +typedef unsigned uint32_least_t; +typedef unsigned long long uint64_least_t; + +typedef int int8_fast_t; +typedef int int16_fast_t; +typedef int int32_fast_t; +typedef long long int64_fast_t; + +typedef unsigned uint8_fast_t; +typedef unsigned uint16_fast_t; +typedef unsigned uint32_fast_t; +typedef unsigned long long uint64_fast_t; + +typedef int intptr_t; +typedef unsigned uintptr_t; + +typedef long long intmax_t; +typedef unsigned long long uintmax_t; diff --git a/include/bits/i386/arch/stdio.h b/include/bits/i386/arch/stdio.h @@ -0,0 +1,15 @@ +#ifndef _SIZET +typedef unsigned long size_t; +#define _SIZET +#endif + +#define BUFSIZ 512 +#define FILENAME_MAX 256 +#define FOPEN_MAX 16 + +#define TMP_MAX 25 +#define L_tmpnam 256 + +#define _TMPNAME "/tmp/tmp.0000000" + +typedef long fpos_t; diff --git a/include/bits/i386/arch/stdlib.h b/include/bits/i386/arch/stdlib.h @@ -0,0 +1,14 @@ +#ifndef _SIZET +typedef unsigned long size_t; +#define _SIZET +#endif + +#define EXIT_FAILURE 1 +#define EXIT_SUCCESS 0 + +#ifndef _WCHAR_T +typedef int wchar_t; +#define _WCHAR_T +#endif + +#define _ALIGNTYPE long double diff --git a/include/bits/i386/arch/string.h b/include/bits/i386/arch/string.h @@ -0,0 +1,5 @@ +#ifndef _SIZET +typedef unsigned long size_t; +#endif + +#define __NUMCHARS 128 diff --git a/include/bits/i386/arch/time.h b/include/bits/i386/arch/time.h @@ -0,0 +1,8 @@ +#ifndef _SIZET +typedef unsigned long size_t; +#define _SIZET +#endif + +#define _MAXYEAR 2037 + +typedef long int time_t; diff --git a/include/bits/linux/sys.h b/include/bits/linux/sys.h @@ -0,0 +1,19 @@ +#define O_RDONLY 0x00000000 +#define O_WRONLY 0x00000001 +#define O_RDWR 0x00000002 + +#define O_TRUNC 0x00000400 +#define O_APPEND 0x00000008 +#define O_CREAT 0x00000200 + +typedef int pid_t; + +struct sigaction { + void (*sa_handler)(int); + int sa_mask; + int sa_flags; +}; + +extern pid_t _getpid(void); +extern int _kill(pid_t pid, int signum); +extern int _sigaction(int sig, struct sigaction *new, struct sigaction *old); diff --git a/include/bits/linux/sys/signal.h b/include/bits/linux/sys/signal.h @@ -0,0 +1,27 @@ +typedef int sig_atomic_t; + +#define SIG_ERR ((void (*)(int))-1) +#define SIG_DFL ((void (*)(int)) 0) +#define SIG_IGN ((void (*)(int)) 1) + +#define SIGHUP 1 +#define SIGINT 2 +#define SIGQUIT 3 +#define SIGILL 4 +#define SIGABRT 6 +#define SIGFPE 8 +#define SIGKILL 9 +#define SIGUSR1 10 +#define SIGSEGV 11 +#define SIGUSR2 12 +#define SIGPIPE 13 +#define SIGALRM 14 +#define SIGTERM 15 +#define SIGCHLD 17 +#define SIGCONT 18 +#define SIGSTOP 19 +#define SIGTSTP 20 +#define SIGTTIN 21 +#define SIGTTOU 22 + +#define __NR_SIGNALS 23 diff --git a/include/bits/netbsd/sys.h b/include/bits/netbsd/sys.h @@ -0,0 +1,19 @@ +#define O_RDONLY 0x00000000 +#define O_WRONLY 0x00000001 +#define O_RDWR 0x00000002 + +#define O_TRUNC 0x00000400 +#define O_APPEND 0x00000008 +#define O_CREAT 0x00000200 + +typedef int pid_t; + +struct sigaction { + void (*sa_handler)(int); + char sa_mask[8]; + int sa_flags; +}; + +extern pid_t _getpid(void); +extern int _kill(pid_t pid, int signum); +extern int _sigaction(int sig, struct sigaction *new, struct sigaction *old); diff --git a/include/bits/netbsd/sys/signal.h b/include/bits/netbsd/sys/signal.h @@ -0,0 +1,27 @@ +typedef int sig_atomic_t; + +#define SIG_ERR ((void (*)(int))-1) +#define SIG_DFL ((void (*)(int)) 0) +#define SIG_IGN ((void (*)(int)) 1) + +#define SIGHUP 1 +#define SIGINT 2 +#define SIGQUIT 3 +#define SIGILL 4 +#define SIGABRT 6 +#define SIGFPE 8 +#define SIGKILL 9 +#define SIGSEGV 11 +#define SIGPIPE 13 +#define SIGALRM 14 +#define SIGTERM 15 +#define SIGSTOP 17 +#define SIGTSTP 18 +#define SIGCONT 19 +#define SIGCHLD 20 +#define SIGTTIN 21 +#define SIGTTOU 22 +#define SIGUSR1 30 +#define SIGUSR2 31 + +#define __NR_SIGNALS 32 diff --git a/include/bits/openbsd/sys.h b/include/bits/openbsd/sys.h @@ -0,0 +1,19 @@ +#define O_RDONLY 0x00000000 +#define O_WRONLY 0x00000001 +#define O_RDWR 0x00000002 + +#define O_TRUNC 0x00000400 +#define O_APPEND 0x00000008 +#define O_CREAT 0x00000200 + +typedef int pid_t; + +struct sigaction { + void (*sa_handler)(int); + int sa_mask; + int sa_flags; +}; + +extern pid_t _getpid(void); +extern int _kill(pid_t pid, int signum); +extern int _sigaction(int sig, struct sigaction *new, struct sigaction *old); diff --git a/include/bits/openbsd/sys/signal.h b/include/bits/openbsd/sys/signal.h @@ -0,0 +1,27 @@ +typedef int sig_atomic_t; + +#define SIG_ERR ((void (*)(int))-1) +#define SIG_DFL ((void (*)(int)) 0) +#define SIG_IGN ((void (*)(int)) 1) + +#define SIGHUP 1 +#define SIGINT 2 +#define SIGQUIT 3 +#define SIGILL 4 +#define SIGABRT 6 +#define SIGFPE 8 +#define SIGKILL 9 +#define SIGSEGV 11 +#define SIGPIPE 13 +#define SIGALRM 14 +#define SIGTERM 15 +#define SIGSTOP 17 +#define SIGTSTP 18 +#define SIGCONT 19 +#define SIGCHLD 20 +#define SIGTTIN 21 +#define SIGTTOU 22 +#define SIGUSR1 30 +#define SIGUSR2 31 + +#define __NR_SIGNALS 32 diff --git a/include/bits/z80/arch/limits.h b/include/bits/z80/arch/limits.h @@ -0,0 +1,18 @@ +#define CHAR_BIT 8 +#define SCHAR_MAX 0x7F +#define SCHAR_MIN (-SCHAR_MIN-1) +#define CHAR_MAX 0xFF +#define CHAR_MIN 0 +#define UCHAR_MAX 0xFF +#define SHRT_MAX 0x7FFF +#define SHRT_MIN (-SHRT_MAX-1) +#define USHRT_MAX 0xFFFF +#define INT_MAX 0x7FFF +#define INT_MIN (-INT_MAX-1) +#define UINT_MAX 0xFFFF +#define LONG_MAX 0x7FFFFFFF +#define LONG_MIN (-LONG_MAX-1) +#define ULONG_MAX 0xFFFFFFFF +#define LLONG_MAX 0x7FFFFFFFFFFFFFFF +#define LLONG_MIN (-LLONG_MAX-1) +#define ULLONG_MAX 0xFFFFFFFFFFFFFFFF diff --git a/include/bits/z80/arch/stddef.h b/include/bits/z80/arch/stddef.h @@ -0,0 +1,14 @@ +#ifndef _SIZET +typedef unsigned size_t; +#define _SIZET +#endif + +#ifndef _WCHAR_T +typedef short wchar_t; +#define _WCHAR_T +#endif + +#ifndef _PTRDIFF_T +typedef short ptrdiff_t; +#define _PTRDIFF_T +#endif diff --git a/include/bits/z80/arch/stdint.h b/include/bits/z80/arch/stdint.h @@ -0,0 +1,115 @@ +#define INT8_MAX 0x7F +#define INT8_MIN (-INT8_MAX-1) +#define UINT8_MAX 0xFF + +#define INT16_MAX 0x7FFF +#define INT16_MIN (-INT16_MAX-1) +#define UINT16_MAX 0xFFFF + +#define INT32_MAX 0x7FFFFFFF +#define INT32_MIN (-INT32_MAX-1) +#define UINT32_MAX 0xFFFFFFFF + +#define INT64_MAX 0x7FFFFFFFFFFFFFFF +#define INT64_MIN (-INT64_MAX-1) +#define UINT64_MAX 0xFFFFFFFFFFFFFFFF + +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST8_MAX INT8_MAX +#define UINT_LEAST8_MAX UINT8_MAX + +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST16_MAX INT16_MAX +#define UINT_LEAST16_MAX UINT16_MAX + +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST32_MAX INT32_MAX +#define UINT_LEAST32_MAX UINT32_MAX + +#define INT_LEAST64_MIN INT64_MIN +#define INT_LEAST64_MAX INT64_MAX +#define UINT_LEAST64_MAX UINT64_MAX + +#define INT_FAST8_MIN INT16_MIN +#define INT_FAST8_MAX INT16_MAX +#define UINT_FAST8_MAX UINT16_MAX + +#define INT_FAST16_MIN INT16_MIN +#define INT_FAST16_MAX INT16_MAX +#define UINT_FAST16_MAX UINT16_MAX + +#define INT_FAST32_MIN INT32_MIN +#define INT_FAST32_MAX INT32_MAX +#define UINT_FAST32_MAX UINT32_MAX + +#define INT_FAST64_MIN INT64_MIN +#define INT_FAST64_MAX INT64_MAX +#define UINT_FAST64_MAX UINT64_MAX + +#define INTPTR_MIN INT16_MIN +#define INTPTR_MAX INT16_MAX +#define UINTPTR_MAX UINT16_MAX + +#define INTMAX_MIN INT64_MIN +#define INTMAX_MAX INT64_MAX +#define UINTMAX_MAX UINT64_MAX + +#define PTRDIFF_MIN INT16_MIN +#define PTRDIFF_MAX INT16_MAX + +#define SIG_ATOMIC_MIN INT16_MIN +#define SIG_ATOMIC_MAX INT16_MAX + +#define SIZE_MAX UINT64_MAX + +#define WCHAR_MIN INT16_MIN +#define WCHAR_MAX INT16_MAX + +#define INT8_C(x) x +#define INT16_C(x) x +#define INT32_C(x) x ## L +#define INT64_C(x) x ## LL + +#define UINT8_C(x) x +#define UINT16_C(x) x ## U +#define UINT32_C(x) x ## UL +#define UINT64_C(x) x ## ULL + +#define INTMAX_C(x) x ## LL +#define UINTMAX_C(x) x ## ULL + +typedef signed char int8_t; +typedef int int16_t; +typedef long int32_t; +typedef long long int64_t; + +typedef unsigned char uint8_t; +typedef unsigned uint16_t; +typedef unsigned long uint32_t; +typedef unsigned long long uint64_t; + +typedef signed char int8_least_t; +typedef int int16_least_t; +typedef long int32_least_t; +typedef long long int64_least_t; + +typedef unsigned char uint8_least_t; +typedef unsigned uint16_least_t; +typedef unsigned long uint32_least_t; +typedef unsigned long long uint64_least_t; + +typedef signed char int8_fast_t; +typedef int int16_fast_t; +typedef long int32_fast_t; +typedef long long int64_fast_t; + +typedef unsigned char uint8_fast_t; +typedef unsigned uint16_fast_t; +typedef unsigned long uint32_fast_t; +typedef unsigned long long uint64_fast_t; + +typedef int intptr_t; +typedef unsigned uintptr_t; + +typedef long long intmax_t; +typedef unsigned long long uintmax_t; diff --git a/include/bits/z80/arch/stdio.h b/include/bits/z80/arch/stdio.h @@ -0,0 +1,15 @@ +#ifndef _SIZET +typedef unsigned size_t; +#define _SIZET +#endif + +#define BUFSIZ 512 +#define FILENAME_MAX 256 +#define FOPEN_MAX 16 + +#define TMP_MAX 25 +#define L_tmpnam 256 + +#define _TMPNAME "TMP.000" + +typedef long fpos_t; diff --git a/include/bits/z80/arch/stdlib.h b/include/bits/z80/arch/stdlib.h @@ -0,0 +1,14 @@ +#ifndef _SIZET +typedef unsigned size_t; +#define _SIZET +#endif + +#define EXIT_FAILURE 1 +#define EXIT_SUCCESS 0 + +#ifndef _WCHAR_T +typedef short wchar_t; +#define _WCHAR_T +#endif + +#define _ALIGNTYPE int diff --git a/include/bits/z80/arch/string.h b/include/bits/z80/arch/string.h @@ -0,0 +1,5 @@ +#ifndef _SIZET +typedef unsigned size_t; +#endif + +#define __NUMCHARS 128 diff --git a/include/bits/z80/arch/time.h b/include/bits/z80/arch/time.h @@ -0,0 +1,8 @@ +#ifndef _SIZET +typedef unsigned size_t; +#define _SIZET +#endif + +#define _MAXYEAR 2037 + +typedef long time_t; diff --git a/include/ctype.h b/include/ctype.h @@ -0,0 +1,45 @@ +#ifndef _CTYPE_H +#define _CTYPE_H + +extern int isalnum(int c); +extern int isalpha(int c); +extern int islower(int c); +extern int isupper(int c); +extern int isdigit(int c); +extern int isxdigit(int c); +extern int iscntrl(int c); +extern int isgraph(int c); +extern int isspace(int c); +extern int isblank(int c); +extern int isprint(int c); +extern int ispunct(int c); +extern int tolower(int c); +extern int toupper(int c); + + +#define _U 0x01 /* upper */ +#define _L 0x02 /* lower */ +#define _D 0x04 /* digit */ +#define _C 0x08 /* cntrl */ +#define _P 0x10 /* punct */ +#define _S 0x20 /* white space (space/lf/tab) */ +#define _X 0x40 /* hex char */ +#define _SP 0x80 /* hard space (0x20) */ + +extern const unsigned char __ctype[]; + +#define isalnum(c) ((__ctype+1)[c] & (_U|_L|_D)) +#define isalpha(c) ((__ctype+1)[c] & (_U|_L)) +#define iscntrl(c) ((__ctype+1)[c] & (_C)) +#define isdigit(c) ((__ctype+1)[c] & (_D)) +#define isgraph(c) ((__ctype+1)[c] & (_P|_U|_L|_D)) +#define islower(c) ((__ctype+1)[c] & (_L)) +#define isprint(c) ((__ctype+1)[c] & (_P|_U|_L|_D|_SP)) +#define ispunct(c) ((__ctype+1)[c] & (_P)) +#define isspace(c) ((__ctype+1)[c] & (_S)) +#define isupper(c) ((__ctype+1)[c] & (_U)) +#define isxdigit(c) ((__ctype+1)[c] & (_D|_X)) + +#define isascii(c) ((unsigned)(c)<=0x7f) + +#endif diff --git a/include/errno.h b/include/errno.h @@ -0,0 +1,6 @@ +#ifndef _ERRNO_H +#define _ERRNO_H + +#include <sys/errno.h> + +#endif diff --git a/include/float.h b/include/float.h @@ -0,0 +1 @@ +/* TODO: Placeholder for compatibility with libraries that need to include it */ diff --git a/include/limits.h b/include/limits.h @@ -0,0 +1,8 @@ +#ifndef _LIMITS_H +#define _LIMITS_H + +#include <arch/limits.h> + +#define MB_LEN_MAX 1 + +#endif diff --git a/include/locale.h b/include/locale.h @@ -0,0 +1,39 @@ +#ifndef _LOCALE_H +#define _LOCALE_H + +#ifndef NULL +#define NULL ((void *) 0) +#endif + +#define LC_ALL 0 +#define LC_COLLATE 1 +#define LC_CTYPE 2 +#define LC_MONETARY 3 +#define LC_NUMERIC 4 +#define LC_TIME 5 + +struct lconv { + char *decimal_point; + char *thousands_sep; + char *grouping; + char *mon_decimal_point; + char *mon_thousands_sep; + char *mon_grouping; + char *positive_sign; + char *negative_sign; + char *currency_symbol; + char *int_curr_symbol; + char frac_digits; + char p_cs_precedes; + char n_cs_precedes; + char p_sep_by_space; + char n_sep_by_space; + char p_sign_posn; + char n_sign_posn; + char int_frac_digits; +}; + +extern char *setlocale(int category, const char *locale); +extern struct lconv *localeconv(void); + +#endif diff --git a/include/math.h b/include/math.h @@ -0,0 +1,4 @@ +#ifndef _MATH_H +#define _MATH_H +#error math.h is not supported yet +#endif diff --git a/include/scc/scc/.gitignore b/include/scc/scc/.gitignore @@ -0,0 +1,5 @@ +cstd.h +ldflags.h +syscrts.h +sysincludes.h +syslibs.h diff --git a/include/scc/scc/Makefile b/include/scc/scc/Makefile @@ -0,0 +1,42 @@ +.POSIX: + +PROJECTDIR = ../../.. +include $(PROJECTDIR)/scripts/rules.mk + +SYSHDR = ldflags.h\ + syscrts.h\ + sysincludes.h\ + syslibs.h \ + cstd.h \ + +all: $(SYSHDR) + +cstd.h: cstd-$(STD).h + cp cstd-$(STD).h $@ + +ldflags.h: + rm -f $@ ; \ + trap "rm -f $$$$.h" 0 2 3; \ + cat < ldflags.def.h > $$$$.h; \ + mv $$$$.h $@ + +syscrts.h: + rm -f $@ ; \ + trap "rm -f $$$$.h" 0 2 3; \ + sed 's,PREFIX,"$(PREFIX)",g' < syscrts.def.h > $$$$.h && \ + mv $$$$.h $@ + +sysincludes.h: + rm -f $@ ; \ + trap "rm -f $$$$.h" 0 2 3; \ + sed 's,PREFIX,"$(PREFIX)",g' < sysincludes.def.h > $$$$.h && \ + mv $$$$.h $@ + +syslibs.h: + rm -f $@ ; \ + trap "rm -f $$$$.h" 0 2 3; \ + sed 's,PREFIX,"$(PREFIX)",g' < syslibs.def.h > $$$$.h && \ + mv $$$$.h $@ + +distclean: + rm -f $(SYSHDR) diff --git a/inc/ar.h b/include/scc/scc/ar.h diff --git a/inc/arg.h b/include/scc/scc/arg.h diff --git a/inc/coff32/aouthdr.h b/include/scc/scc/coff32/aouthdr.h diff --git a/inc/coff32/coff32.h b/include/scc/scc/coff32/coff32.h diff --git a/inc/coff32/filehdr.h b/include/scc/scc/coff32/filehdr.h diff --git a/inc/coff32/linenum.h b/include/scc/scc/coff32/linenum.h diff --git a/inc/coff32/reloc.h b/include/scc/scc/coff32/reloc.h diff --git a/inc/coff32/scnhdr.h b/include/scc/scc/coff32/scnhdr.h diff --git a/inc/coff32/syms.h b/include/scc/scc/coff32/syms.h diff --git a/inc/c89/cstd.h b/include/scc/scc/cstd-c89.h diff --git a/inc/c99/cstd.h b/include/scc/scc/cstd-c99.h diff --git a/inc/ldflags.def.h b/include/scc/scc/ldflags.def.h diff --git a/inc/myro.h b/include/scc/scc/myro.h diff --git a/inc/scc.h b/include/scc/scc/scc.h diff --git a/inc/syscrts.def.h b/include/scc/scc/syscrts.def.h diff --git a/inc/sysincludes.def.h b/include/scc/scc/sysincludes.def.h diff --git a/inc/syslibs.def.h b/include/scc/scc/syslibs.def.h diff --git a/include/setjmp.h b/include/setjmp.h @@ -0,0 +1,11 @@ +#ifndef _SETJMP_H +#define _SETJMP_H + +#include <arch/setjmp.h> + +extern int setjmp(jmp_buf env); +extern void longjmp(jmp_buf env, int val); + +#define setjmp setjmp + +#endif diff --git a/include/signal.h b/include/signal.h @@ -0,0 +1,9 @@ +#ifndef _SIGNAL_H +#define _SIGNAL_H + +#include <sys/signal.h> + +void ( *signal(int signum, void (*handler)(int)) ) (int); +int raise(int sig); + +#endif diff --git a/include/stdarg.h b/include/stdarg.h @@ -0,0 +1,10 @@ +#ifndef _STDARG_H +#define _STDARG_H + +typedef __builtin_va_list va_list; +#define va_start(ap, last) __builtin_va_start(ap, last) +#define va_end(ap) __builtin_va_end(ap) +#define va_copy(to, from) __builtin_va_copy(to, from) +#define va_arg(to, type) __builtin_va_arg(to, type) + +#endif diff --git a/include/stdbool.h b/include/stdbool.h @@ -0,0 +1,9 @@ +#ifndef _STDBOOL_H +#define _STDBOOL_H + +#define bool _Bool +#define true 1 +#define false 0 +#define __bool_true_false_are_defined 1 + +#endif diff --git a/include/stddef.h b/include/stddef.h @@ -0,0 +1,12 @@ +#ifndef _STDDEF_H +#define _STDDEF_H + +#include <arch/stddef.h> + +#ifndef NULL +#define NULL ((void *) 0) +#endif + +#define offsetof(st, m) ((size_t)&(((st *)0)->m)) + +#endif diff --git a/include/stdint.h b/include/stdint.h @@ -0,0 +1,6 @@ +#ifndef _STDINT_H_ +#define _STDINT_H_ + +#include <arch/stdint.h> + +#endif diff --git a/include/stdio.h b/include/stdio.h @@ -0,0 +1,123 @@ +#ifndef _STDIO_H +#define _STDIO_H + +#include <arch/stdio.h> + +#ifndef FOPEN_MAX +#define FOPEN_MAX 12 +#endif + +#ifndef NULL +#define NULL ((void *) 0) +#endif + +#define EOF -1 +#define SEEK_CUR 0 +#define SEEK_END 1 +#define SEEK_SET 2 + + +#define _IOWRITE (1 << 0) +#define _IOREAD (1 << 1) +#define _IORW (1 << 2) +#define _IOEOF (1 << 3) +#define _IOERR (1 << 4) +#define _IOSTRG (1 << 5) +#define _IOTXT (1 << 6) +#define _IOFBF (1 << 7) +#define _IOLBF (1 << 8) +#define _IONBF (1 << 9) +#define _IOALLOC (1 <<10) + +typedef struct { + int fd; /* file descriptor */ + unsigned char *buf; /* pointer to i/o buffer */ + unsigned char *rp; /* read pointer */ + unsigned char *wp; /* write pointer */ + unsigned char *lp; /* write pointer used when line-buffering */ + size_t len; /* actual length of buffer */ + unsigned short flags; + unsigned char unbuf[1]; /* tiny buffer for unbuffered io */ +} FILE; + +extern FILE __iob[FOPEN_MAX]; + +#define stdin (&__iob[0]) +#define stdout (&__iob[1]) +#define stderr (&__iob[2]) + +extern int remove(const char *filename); +extern int rename(const char *old, const char *new); +extern FILE *tmpfile(void); +extern char *tmpnam(char *s); +extern int fclose(FILE *fp); +extern int fflush(FILE *fp); +extern FILE *fopen(const char * restrict fname, const char * restrict mode); +extern FILE *freopen(const char * restrict fname, const char * restrict mode, + FILE * restrict fp); +extern void setbuf(FILE * restrict fp, char * restrict buf); +extern int setvbuf(FILE * restrict fp, + char * restrict buf, int mode, size_t size); +extern int fprintf(FILE * restrict fp, const char * restrict fmt, ...); +extern int fscanf(FILE * restrict fp, const char * restrict fmt, ...); +extern int printf(const char * restrict fmt, ...); +extern int scanf(const char * restrict fmt, ...); +extern int snprintf(char * restrict s, + size_t n, const char * restrict fmt, ...); +extern int sprintf(char * restrict s, const char * restrict fmt, ...); +extern int sscanf(const char * restrict s, const char * restrict fmt, ...); + +#ifdef _STDARG_H +extern int vfprintf(FILE * restrict fp, + const char * restrict fmt, va_list arg); +extern int vfscanf(FILE * restrict fp, + const char * restrict fmt, va_list arg); +extern int vprintf(const char * restrict fmt, va_list arg); +extern int vscanf(const char * restrict fmt, va_list arg); +extern int vsnprintf(char * restrict s, size_t n, const char * restrict fmt, + va_list arg); +extern int vsprintf(char * restrict s, + const char * restrict fmt, va_list arg); +extern int vsscanf(const char * restrict s, + const char * restrict fmt, va_list arg); +#endif + +extern int fgetc(FILE *fp); +extern char *fgets(char * restrict s, int n, FILE * restrict fp); +extern int fputc(int c, FILE *fp); +extern int fputs(const char * restrict s, FILE * restrict fp); +extern int getc(FILE *fp); +extern int getchar(void); +extern char *gets(char *s); +extern int putc(int c, FILE *fp); +extern int putchar(int c); +extern int puts(const char *s); +extern int ungetc(int c, FILE *fp); +extern size_t fread(void * restrict ptr, size_t size, size_t nmemb, + FILE * restrict fp); +extern size_t fwrite(const void * restrict ptr, size_t size, size_t nmemb, + FILE * restrict fp); +extern int fgetpos(FILE * restrict fp, fpos_t * restrict pos); +extern int fseek(FILE *fp, long int offset, int whence); +extern int fsetpos(FILE *fp, const fpos_t *pos); +extern long int ftell(FILE *fp); +extern void rewind(FILE *fp); +extern void clearerr(FILE *fp); +extern int feof(FILE *fp); +extern int ferror(FILE *fp); +extern void perror(const char *s); + +extern int __getc(FILE *fp); +extern int __putc(int, FILE *fp); + +#define getc(fp) ((fp)->rp >= (fp)->wp ? __getc(fp) : *(fp)->rp++) +#define putc(c, fp) ((fp)->wp >= (fp)->rp ? __putc(c,fp) : (*(fp)->wp++ = c)) + +#define ferror(fp) ((fp)->flags & _IOERR) +#define feof(fp) ((fp)->flags & _IOEOF) +#define clearerr(fp) (void) ((fp)->flags &= ~(_IOERR|_IOEOF)) +#define getchar() getc(stdin) +#define putchar(c) putc((c), stdout) +#define setbuf(fp, b) (void) setvbuf(fp, b, b ? _IOFBF:_IONBF, BUFSIZ) + +#endif diff --git a/include/stdlib.h b/include/stdlib.h @@ -0,0 +1,69 @@ +#ifndef _STDLIB_H +#define _STDLIB_H + +#include <arch/stdlib.h> + +#ifndef NULL +#define NULL ((void *) 0) +#endif + +#define _ATEXIT_MAX 32 + +#define MB_CUR_MAX 1 +#define RAND_MAX 32767 + +typedef struct { + int quot, rem; +} div_t; + +typedef struct { + long quot, rem; +} ldiv_t; + +typedef struct { + long long quot, rem; +} lldiv_t; + +extern double atof(const char *nptr); +extern int atoi(const char *nptr); +extern long int atol(const char *nptr); +extern long long int atoll(const char *nptr); +extern double strtod(const char * restrict nptr, char ** restrict endptr); +extern float strtof(const char * restrict nptr, char ** restrict endptr); +extern long double strtold(const char * restrict nptr, char ** restrict endptr); +extern long int strtol(const char * restrict nptr, char ** restrict endptr, int base); +extern long long int strtoll(const char * restrict nptr, char ** restrict endptr, + int base); +extern unsigned long int strtoul(const char * restrict nptr, char ** restrict endptr, + int base); +extern unsigned long long int strtoull(const char * restrict nptr, + char ** restrict endptr, int base); +extern int rand(void); +extern void srand(unsigned int seed); +extern void *calloc(size_t nmemb, size_t size); +extern void free(void *ptr); +extern void *malloc(size_t size); +extern void *realloc(void *ptr, size_t size); +extern void abort(void); +extern int atexit(void (*func)(void)); +extern void exit(int status); +extern void _Exit(int status); +extern char *getenv(const char *name); +extern int system(const char *string); +extern void *bsearch(const void *key, const void *base, size_t nmemb, size_t size, + int (*compar)(const void *, const void *)); +extern void qsort(void *base, size_t nmemb, size_t size, + int (*compar)(const void *, const void *)); +extern int abs(int j); +extern long int labs(long int j); +extern long long int llabs(long long int j); +extern div_t div(int numer, int denom); +extern ldiv_t ldiv(long int numer, long int denom); +extern lldiv_t lldiv(long long int numer, long long int denom); +extern int mblen(const char *s, size_t n); +extern int mbtowc(wchar_t * restrict pwc, const char * restrict s, size_t n); +extern int wctomb(char *s, wchar_t wchar); +extern size_t mbstowcs(wchar_t * restrict pwcs, const char * restrict s, size_t n); +extern size_t wcstombs(char * restrict s, const wchar_t * restrict pwcs, size_t n); + +#endif diff --git a/include/string.h b/include/string.h @@ -0,0 +1,34 @@ +#ifndef _STRING_H +#define _STRING_H + +#include <arch/string.h> + +#ifndef NULL +#define NULL ((void *) 0) +#endif + +extern void *memcpy(void * restrict s1, const void * restrict s2, size_t n); +extern void *memmove(void *s1, const void *s2, size_t n); +extern char *strcpy(char * restrict s1, const char * restrict s2); +extern char *strncpy(char * restrict s1, const char * restrict s2, size_t n); +extern char *strcat(char * restrict s1, const char * restrict s2); +extern char *strncat(char * restrict s1, const char * restrict s2, size_t n); +extern int memcmp(const void *s1, const void *s2, size_t n); +extern int strcmp(const char *s1, const char *s2); +extern int strcoll(const char *s1, const char *s2); +extern int strncmp(const char *s1, const char *s2, size_t n); +extern size_t strxfrm(char * restrict s1, const char * restrict s2, size_t n); +extern void *memchr(const void *s, int c, size_t n); +extern char *strchr(const char *s, int c); +extern size_t strcspn(const char *s1, const char *s2); +extern char *strpbrk(const char *s1, const char *s2); +extern char *strrchr(const char *s, int c); +extern size_t strspn(const char *s1, const char *s2); +extern char *strstr(const char *s1, const char *s2); +extern char *strtok(char * restrict s1, const char * restrict s2); +extern void *memset(void *s, int c, size_t n); +extern char *strerror(int errnum); +extern size_t strlen(const char *s); +extern size_t strnlen(const char *s, size_t maxlen); + +#endif diff --git a/include/time.h b/include/time.h @@ -0,0 +1,43 @@ +#ifndef _TIME_H +#define _TIME_H + +#include <arch/time.h> + +#ifndef NULL +#define NULL ((void *) 0) +#endif + +#define CLOCKS_PER_SEC 1000000 + +typedef long int clock_t; + +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; + + /* fields used internally */ + + char *tm_zone; + long tm_gmtoff; +}; + +extern clock_t clock(void); +extern double difftime(time_t time1, time_t time0); +extern time_t mktime(struct tm *timeptr); +extern time_t time(time_t *timer); +extern char *asctime(const struct tm *timeptr); +extern char *ctime(const time_t *timer); +extern struct tm *gmtime(const time_t *timer); +extern struct tm *localtime(const time_t *timer); +extern size_t strftime(char * restrict s, size_t maxsize, + const char * restrict format, + const struct tm * restrict timeptr); + +#endif diff --git a/include/wchar.h b/include/wchar.h @@ -0,0 +1,92 @@ +#ifndef _WCHAR_H +#define _WCHAR_H + +/* TODO: This is only a placeholder */ +typedef long wchar_t; +/* typedef long size_t; */ +typedef long mbstate_t; +typedef long wint_t; +struct tm; + +/* #define WCHAR_MAX 1 */ +/* #define WCHAR_MIN 1 */ +/* #define WEOF -1 */ +/* #define NULL 0 */ + +#ifdef _STDARG_H +extern int vswscanf(const wchar_t * restrict s, const wchar_t * restrict format, va_list arg); +extern int vwprintf(const wchar_t * restrict format, va_list arg); +extern int vwscanf(const wchar_t * restrict format, va_list arg); +#endif + +#ifdef _STDIO_H +extern int fwprintf(FILE * restrict stream, const wchar_t * restrict format, ...); +extern int fwscanf(FILE * restrict stream, const wchar_t * restrict format, ...); + +#ifdef _STDARG_H +extern int vfwprintf(FILE * restrict stream, const wchar_t * restrict format, va_list arg); +extern int vfwscanf(FILE * restrict stream, const wchar_t * restrict format, va_list arg); +extern int vswprintf(wchar_t * restrict s, size_t n, const wchar_t * restrict format, va_list arg); +#endif + +extern wint_t fgetwc(FILE *stream); +extern wint_t fputwc(wchar_t c, FILE *stream); +extern wint_t getwc(FILE *stream); +extern wint_t putwc(wchar_t c, FILE *stream); +extern int fwide(FILE *stream, int mode); +extern wint_t ungetwc(wint_t c, FILE *stream); +extern wchar_t *fgetws(wchar_t * restrict s, int n, FILE * restrict stream); +extern int fputws(const wchar_t * restrict s, FILE * restrict stream); +#endif + +extern int swprintf(wchar_t * restrict s, size_t n, const wchar_t * restrict format, ...); +extern int swscanf(const wchar_t * restrict s, const wchar_t * restrict format, ...); +extern int wprintf(const wchar_t * restrict format, ...); +extern int wscanf(const wchar_t * restrict format, ...); + +extern wint_t getwchar(void); +extern wint_t putwchar(wchar_t c); + +extern double wcstod(const wchar_t * restrict nptr, wchar_t ** restrict endptr); +extern float wcstof(const wchar_t * restrict nptr, wchar_t ** restrict endptr); +extern long double wcstold(const wchar_t * restrict nptr, wchar_t ** restrict endptr); + +extern long int wcstol(const wchar_t * restrict nptr, wchar_t ** restrict endptr, int base); +extern long long int wcstoll(const wchar_t * restrict nptr, wchar_t ** restrict endptr, int base); +extern unsigned long int wcstoul(const wchar_t * restrict nptr, wchar_t ** restrict endptr, int base); +extern unsigned long long int wcstoull(const wchar_t * restrict nptr, wchar_t ** restrict endptr, int base); + +extern wchar_t *wcscpy(wchar_t * restrict s1, const wchar_t * restrict s2); +extern wchar_t *wcsncpy(wchar_t * restrict s1, const wchar_t * restrict s2, size_t n); + +extern wchar_t *wmemcpy(wchar_t * restrict s1, const wchar_t * restrict s2, size_t n); +extern wchar_t *wmemmove(wchar_t *s1, const wchar_t *s2, size_t n); +extern wchar_t *wcscat(wchar_t * restrict s1, const wchar_t * restrict s2); +extern wchar_t *wcsncat(wchar_t * restrict s1, const wchar_t * restrict s2, size_t n); +extern int wcscmp(const wchar_t *s1, const wchar_t *s2); +extern int wcscoll(const wchar_t *s1, const wchar_t *s2); +extern int wcsncmp(const wchar_t *s1, const wchar_t *s2, size_t n); +extern size_t wcsxfrm(wchar_t * restrict s1, const wchar_t * restrict s2, size_t n); +extern int wmemcmp(const wchar_t *s1, const wchar_t *s2, size_t n); +extern wchar_t *wcschr(const wchar_t *s, wchar_t c); +extern size_t wcscspn(const wchar_t *s1, const wchar_t *s2); +extern wchar_t *wcspbrk(const wchar_t *s1, const wchar_t *s2); +extern wchar_t *wcsrchr(const wchar_t *s, wchar_t c); +extern size_t wcsspn(const wchar_t *s1, const wchar_t *s2); +extern wchar_t *wcsstr(const wchar_t *s1, const wchar_t *s2); +extern wchar_t *wcstok(wchar_t * restrict s1, const wchar_t * restrict s2, wchar_t ** restrict ptr); +extern wchar_t *wmemchr(const wchar_t *s, wchar_t c, size_t n); +extern size_t wcslen(const wchar_t *s); +extern wchar_t *wmemset(wchar_t *s, wchar_t c, size_t n); +extern size_t wcsftime(wchar_t * restrict s, size_t maxsize, const wchar_t * restrict format, const struct tm * restrict timeptr); +extern wint_t btowc(int c); +extern int wctob(wint_t c); +extern int mbsinit(const mbstate_t *ps); +extern size_t mbrlen(const char * restrict s, size_t n, mbstate_t * restrict ps); +extern size_t mbrtowc(wchar_t * restrict pwc, const char * restrict s, size_t n, mbstate_t * restrict ps); +extern size_t wcrtomb(char * restrict s, wchar_t wc, mbstate_t * restrict ps); +extern size_t mbsrtowcs(wchar_t * restrict dst, const char ** restrict src, size_t len, mbstate_t * restrict ps); +extern size_t wcsrtombs(char * restrict dst, const wchar_t ** restrict src, size_t len, mbstate_t * restrict ps); + + +#endif diff --git a/include/wctype.h b/include/wctype.h @@ -0,0 +1,30 @@ +#ifndef _WCTYPE_H +#define _WCTYPE_H + +/* TODO: This is only a placeholder */ +typedef int wint_t; +typedef int wctrans_t; +typedef int wctype_t; + +#define WEOF -1 + +extern int iswalnum(wint_t wc); +extern int iswalpha(wint_t wc); +extern int iswblank(wint_t wc); +extern int iswcntrl(wint_t wc); +extern int iswdigit(wint_t wc); +extern int iswgraph(wint_t wc); +extern int iswlower(wint_t wc); +extern int iswprint(wint_t wc); +extern int iswpunct(wint_t wc); +extern int iswspace(wint_t wc); +extern int iswupper(wint_t wc); +extern int iswxdigit(wint_t wc); +extern int iswctype(wint_t wc, wctype_t desc); +extern wctype_t wctype(const char *property); +extern wint_t towlower(wint_t wc); +extern wint_t towupper(wint_t wc); +extern wint_t towctrans(wint_t wc, wctrans_t desc); +extern wctrans_t wctrans(const char *property); + +#endif diff --git a/ld/Makefile b/ld/Makefile @@ -1,23 +0,0 @@ -.POSIX: - -PROJECTDIR = .. -include $(PROJECTDIR)/rules.mk -include $(LIBSCC)/libdep.mk -include $(LIBCOFF32)/libdep.mk - -OBJ = main.o coff32.o obj.o -LIB = $(LIBDIR)/libscc.a $(LIBDIR)/libcoff32.a -TARGET = ld - -all: $(TARGET) - -$(TARGET): $(OBJ) $(LIB) - $(CC) $(SCC_LDFLAGS) $(OBJ) -lcoff32 -lscc -o $@ - -dep: - $(PROJECTDIR)/mkdep.sh - -clean: - rm -f $(BINDIR)/ld *.o - -include deps.mk diff --git a/ld/coff32.c b/ld/coff32.c @@ -1,403 +0,0 @@ -static char sccsid[] = "@(#) ./ld/coff32.c"; - -#include <assert.h> -#include <ctype.h> -#include <errno.h> -#include <limits.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "../inc/coff32/aouthdr.h" -#include "../inc/coff32/filehdr.h" -#include "../inc/coff32/scnhdr.h" -#include "../inc/coff32/syms.h" -#include "../inc/coff32/coff32.h" -#include "../inc/scc.h" -#include "ld.h" - -#define NUMSCN_MAX 65536 -#define NUMENT_MAX 2147483648 - -static long textpc = 0x1000; - -/* - * check overflow in: off + ptr + nitem*size - */ -static char * -symname(Obj *obj, SYMENT *ent) -{ - long off; - - if (ent->n_zeroes != 0) - return ent->n_name; - - off = ent->n_offset; - if (off >= obj->strsiz) { - fprintf(stderr, - "ld: invalid offset in symbol table: %zd\n", off); - return ""; - } - - return &obj->strtbl[off]; -} - -static int -readstr(Obj *obj, long off) -{ - unsigned char buff[4]; - char *str; - size_t siz; - - if (fseek(obj->fp, off, SEEK_SET) == EOF) - return -1; - - if (fread(buff, 4, 1, obj->fp) != 1) - return -1; - - (*obj->unpack)(buff, "l", &siz); - - siz -= 4; - if (siz == 0) { - obj->strtbl = NULL; - obj->strsiz = 0; - return 0; - } - - if (siz > SIZE_MAX || (str = malloc(siz)) == NULL) - outmem(); - - if (fread(str, siz, 1, obj->fp) != 1) - return -1; - - obj->strtbl = str; - obj->strsiz = siz; - - return 0; -} - -static int -readsects(Obj *obj, long off) -{ - unsigned a, nsec, i; - unsigned char buff[SCNHSZ]; - SCNHDR *scns, *p; - FILHDR *hdr; - Symbol *sym; - Section *sp; - - hdr = obj->filhdr; - nsec = hdr->f_nscns; - - scns = NULL; - if (nsec <= SIZE_MAX / sizeof(*scns)) - scns = malloc(nsec * sizeof(*scns)); - if (!scns) - outmem(); - obj->scnhdr = scns; - - if (fseek(obj->fp, off, SEEK_SET) == EOF) - return -1; - - a = obj->align - 1; - for (i = 0; i < nsec; ++i) { - p = &scns[i]; - if (fread(buff, SCNHSZ, 1, obj->fp) != 1) - return -1; - coff32_unpack_scn(obj->unpack, buff, p); - sp = slookup(p->s_name); - p->s_vaddr = sp->base + sp->size; - sp->size += p->s_size; - } - - return 0; -} - -static int -readents(Obj *obj, long off) -{ - SYMENT *ent, *ents; - SCNHDR *scn, *scns = obj->scnhdr; - FILHDR *hdr = obj->filhdr;; - long nsyms = hdr->f_nsyms; - unsigned nsect; - unsigned char buff[SYMESZ]; - char *s; - int aux; - Symbol *sym; - - - if (fseek(obj->fp, off, SEEK_SET) == EOF) - return -1; - - ents = NULL; - if (nsyms <= SIZE_MAX/sizeof(SYMENT)) - ents = malloc((nsyms * sizeof(SYMENT))); - if (!ents) - outmem(); - obj->enthdr = ents; - - aux = 0; - for (ent = ents; ent < &ents[nsyms]; ++ent) { - if (fread(buff, SYMESZ, 1, obj->fp) != 1) - return -1; - coff32_unpack_ent(obj->unpack, buff, ent); - s = ent->n_name; - if (!s[0] && !s[1] && !s[2] && !s[3]) - (*obj->unpack)(buff, "ll", &ent->n_zeroes, &ent->n_offset); - - if (aux > 0) { - aux--; - continue; - } - aux = ent->n_numaux; - - scn = NULL; - switch (ent->n_scnum) { - case N_DEBUG: - continue; - case N_ABS: - break; - case N_UNDEF: - /* TODO: deal wth common blocks */ - break; - default: - nsect = ent->n_scnum-1; - if (nsect >= hdr->f_nscns) - corrupted(obj->fname, obj->member); - scn = &scns[nsect]; - ent->n_value += scn->s_vaddr; - } - - if (ent->n_sclass == C_EXT && ent->n_scnum != N_UNDEF) { - Symbol *sym = lookup(symname(obj, ent), INSTALL); - - if (sym->flags & SDEFINED) { - redefined(obj, sym); - } else { - sym->flags |= SDEFINED; - sym->where = obj; - if (scn) - sym->section = slookup(scn->s_name); - } - } - } - - return 0; -} - -static long -fileptr(long off, long ptr, long nitem, long size) -{ - if (off < 0 || ptr < 0 || nitem < 0 || size < 0) - return -1; - - if (off > LONG_MAX - ptr) - return -1; - off += ptr; - - if (size > 0) { - if (nitem > LONG_MAX / size) - return -1; - size *= nitem; - } - - if (off > LONG_MAX - size) - return -1; - off += size; - - return off; -} - -Obj * -load(Obj *obj) -{ - unsigned char buff[FILHSZ]; - FILHDR *hdr; - char *strtbl; - long symoff, secoff, stroff, pos; - - pos = ftell(obj->fp); - if (fread(buff, FILHSZ, 1, obj->fp) != 1) - goto bad_file; - - if ((hdr = malloc(sizeof(*hdr))) == NULL) - outmem(); - coff32_unpack_hdr(obj->unpack, buff, hdr); - obj->filhdr = hdr; - - stroff = fileptr(pos, hdr->f_symptr, hdr->f_nsyms, SYMESZ); - symoff = fileptr(pos, hdr->f_symptr, 0, 0); - secoff = fileptr(pos, hdr->f_opthdr, 1, FILHSZ); - - if (stroff < 0 || symoff < 0 || secoff < 0) - goto bad_file; - - if (readstr(obj, stroff) < 0) - goto bad_file; - if (readsects(obj, secoff) < 0) - goto bad_file; - if (readents(obj, symoff) < 0) - goto bad_file; - return add(obj); - -bad_file: - fprintf(stderr, - "ld: %s: %s\n", - obj->fname, - (ferror(obj->fp)) ? strerror(errno) : "corrupted file"); - exit(EXIT_FAILURE); -} - -Obj * -probe(char *fname, char *member, FILE *fp) -{ - int c; - int c1, c2; - long pos; - unsigned short magic; - unsigned align; - int (*unpack)(unsigned char *, char *, ...); - int (*pack)(unsigned char *, char *, ...); - Obj *obj; - - pos = ftell(fp); - c1 = getc(fp); - c2 = getc(fp); - fseek(fp, pos, SEEK_SET); - - if (ferror(fp)) - die("ld: %s: %s", fname, strerror(errno)); - - if (c1 == EOF || c2 == EOF) - return 0; - magic = c1 | c2 << 8; - - switch (magic) { - case COFF_I386MAGIC: - case COFF_Z80MAGIC: - unpack = lunpack; - pack = lpack; - align = 2; - break; - default: - return NULL; - } - - obj = newobj(fname, member, fp); - obj->unpack = unpack; - obj->align = align; - obj->offset = pos; - - return obj; -} - -static void -wrhdr(FILE *fp) -{ - FILHDR hdr; - Section *sp; - unsigned char buff[FILHSZ]; - - if (numsects > NUMSCN_MAX || numsymbols > NUMENT_MAX) { - fprintf(stderr, "ld: too many symbols or sections\n"); - exit(EXIT_FAILURE); - } - - /* - * we set the timestamp to 0 to make the output - * reproductible and to avoid a not standard use - * of time() - */ - hdr.f_symptr = 0; - hdr.f_magic = COFF_Z80MAGIC; - hdr.f_nscns = numsects; - hdr.f_symptr = 0; - hdr.f_timdat = 0; - hdr.f_nsyms = 0; - hdr.f_opthdr = AOUTSZ; - hdr.f_flags = F_EXEC | F_AR32WR; /* TODO: set the correct endianess */ - - if (!sflag) { - hdr.f_symptr = 0; /* TODO: set correct value here */ - hdr.f_flags |= F_SYMS; - hdr.f_nsyms = numsymbols; - } - - coff32_pack_hdr(lpack, buff, &hdr); - fwrite(buff, FILHSZ, 1, fp); -} - -static void -wraout(FILE *fp) -{ - AOUTHDR aout; - unsigned char buff[AOUTSZ]; - Symbol *sym; - long addr; - - if ((sym = lookup(entry, NOINSTALL)) != NULL) { - addr = sym->value; - } else { - fprintf(stderr, - "ld: warning: cannot find entry symbol '%s'; defaulting to 0\n", - entry); - addr = 0; - } - - aout.magic = ZMAGIC; - aout.vstamp = 0; - aout.entry = addr; - aout.tsize = tsize; - aout.dsize = dsize; - aout.bsize = bsize; - aout.text_start = textpc; - aout.data_start = textpc + dsize; - - coff32_pack_aout(lpack, buff, &aout); - fwrite(buff, AOUTSZ, 1, fp); -} - -static void -wrscn(FILE *fp, Section *sp, long pc) -{ - SCNHDR scn; - unsigned char buff[SCNHSZ]; - - strcpy(scn.s_name, sp->name); - scn.s_paddr = pc; - scn.s_vaddr = pc; - scn.s_size = sp->size; - scn.s_scnptr = 0; /* TODO: file ptr */ - scn.s_relptr = 0; - scn.s_lnnoptr = 0; - scn.s_nrelloc = 0; - scn.s_nlnno = 0; - scn.s_flags = 0; /* TODO: Add flags */ - - coff32_pack_scn(lpack, buff, &scn); - fwrite(buff, SCNHSZ, 1, fp); -} - -void -writeout(FILE *fp) -{ - Section *sp; - long pc = textpc; - - wrhdr(fp); - wraout(fp); - - for (sp = sectlst; sp; sp = sp->next) { - wrscn(fp, sp, pc); - pc += sp->size; - } - - /* TODO: run over all the files */ - - if (fflush(fp) == EOF) { - perror("ld: error writing output file"); - exit(EXIT_FAILURE); - } -} diff --git a/ld/deps.mk b/ld/deps.mk @@ -1,15 +0,0 @@ - -#deps -coff32.o: ../inc/coff32/aouthdr.h -coff32.o: ../inc/coff32/coff32.h -coff32.o: ../inc/coff32/filehdr.h -coff32.o: ../inc/coff32/scnhdr.h -coff32.o: ../inc/coff32/syms.h -coff32.o: ../inc/scc.h -coff32.o: ld.h -main.o: ../inc/ar.h -main.o: ../inc/scc.h -main.o: ../inc/syslibs.h -main.o: ld.h -obj.o: ../inc/scc.h -obj.o: ld.h diff --git a/ld/main.c b/ld/main.c @@ -1,288 +0,0 @@ -static char sccsid[] = "@(#) ./ld/main.c"; - -#include <ctype.h> -#include <errno.h> -#include <limits.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "../inc/scc.h" -#include "../inc/ar.h" -#include "../inc/syslibs.h" -#include "ld.h" - -char *output = "a.out", *entry = "start", *datasiz; -int pass; -int sflag; /* discard all the symbols */ -int xflag; /* discard local symbols */ -int Xflag; /* discard locals starting with 'L' */ -int rflag; /* preserve relocation bits */ -int dflag; /* define common even with rflag */ -int gflag; /* preserve debug symbols */ - -static int done; - -void -redefined(Obj *obj, Symbol *sym) -{ - /* TODO: add infotmation about where it is defined */ - fprintf(stderr, - "ld: %s: redifinition of symbol '%s'\n", - obj->fname, sym->name); -} - -void -corrupted(char *fname, char *member) -{ - char *fmt; - - fmt = (member) ? - "ld: %s(%s): corrupted file\n" : "ld: %s: corrupted file\n"; - fprintf(stderr, fmt, fname, member); - exit(EXIT_FAILURE); -} - -void -outmem(void) -{ - fputs("ld: out of memory\n", stderr); - exit(EXIT_FAILURE); -} - -static void -cleanup(void) -{ - if (!done) - remove(output); -} - -static int -object(char *fname, char *member, FILE *fp) -{ - Obj *obj; - - obj = probe(fname, member, fp); - if (!obj) - return 0; - load(obj); - - return 1; -} - -static char * -getfname(struct ar_hdr *hdr, char *dst) -{ - char *p; - int i; - - memcpy(dst, hdr->ar_name, SARNAM); - dst[SARNAM] = '\0'; - - for (i = SARNAM-1; i >= 0; i--) { - if (dst[i] != ' ' && dst[i] != '/') - break; - dst[i] = '\0'; - } - return dst; -} - -static void -ar(char *fname, FILE *fp) -{ - struct ar_hdr hdr; - long pos, siz; - char member[SARNAM+1]; - - if (fseek(fp, SARMAG, SEEK_SET) == EOF) - goto file_error; - - while (fread(&hdr, sizeof(hdr), 1, fp) == 1) { - if (strncmp(hdr.ar_fmag, ARFMAG, sizeof(hdr.ar_fmag))) - corrupted(fname, NULL); - - siz = 0; - sscanf(hdr.ar_size, "%10ld", &siz); - if (siz & 1) - siz++; - if (siz == 0) - corrupted(fname, NULL); - - pos = ftell(fp); - if (pos == -1 || pos > LONG_MAX - siz) { - fprintf(stderr, - "ld: %s(%s): overflow in size of archive", - fname, member); - exit(EXIT_FAILURE); - } - pos += siz; - - getfname(&hdr, member); - object(fname, member, fp); - if (fseek(fp, pos, SEEK_SET) == EOF) - break; - } - -file_error: - if (ferror(fp)) { - fprintf(stderr, "ld: %s: %s\n", fname, strerror(errno)); - exit(EXIT_FAILURE); - } -} - -static int -archive(char *fname, FILE *fp) -{ - char magic[SARMAG]; - fpos_t pos; - - fgetpos(fp, &pos); - fread(magic, SARMAG, 1, fp); - fsetpos(fp, &pos); - - if (ferror(fp)) - return 0; - if (strncmp(magic, ARMAG, SARMAG) != 0) - return 0; - - ar(fname, fp); - return 1; -} - -static void -pass1(int argc, char *argv[]) -{ - FILE *fp; - char *s; - - while ((s = *argv++) != NULL) { - if ((fp = fopen(s, "rb")) == NULL) { - fprintf(stderr, "ld: %s: %s\n", s, strerror(errno)); - exit(EXIT_FAILURE); - } - if (!object(s, NULL, fp) && !archive(s, fp)) { - fprintf(stderr, "ld: %s: File format not recognized\n", s); - exit(EXIT_FAILURE); - } - fclose(fp); - } -} - -static void -pass2(int argc, char *argv[]) -{ - FILE *fp; - - if ((fp = fopen(output, "wb")) != NULL) { - writeout(fp); - if (fclose(fp) != EOF) - return; - } - - fprintf(stderr, "ld: %s: %s\n", output, strerror(errno)); - exit(EXIT_FAILURE); -} - -static void -usage(void) -{ - fputs("usage: ld [options] file ...\n", stderr); - exit(1); -} - -static void -Lpath(char *path) -{ - char **bp; - - for (bp = syslibs; bp < &syslibs[MAX_LIB_PATHS] && *bp; ++bp) - ; - if (bp == &syslibs[MAX_LIB_PATHS]) { - fputs("ld: too many -L options\n", stderr); - exit(1); - } - *bp = path; -} - -int -main(int argc, char *argv[]) -{ - char *cp, **p; - - for (--argc; *++argv; --argc) { - if (argv[0][0] != '-' || argv[0][1] == 'l') - break; - if (argv[0][1] == '-') { - --argc, ++argv; - break; - } - for (cp = &argv[0][1]; *cp; ++cp) { - switch (*cp) { - case 's': - sflag = 1; - break; - case 'x': - xflag = 1; - break; - case 'X': - Xflag = 1; - break; - case 'r': - rflag = 1; - break; - case 'd': - dflag = 1; - break; - case 'i': - case 'n': - /* TODO */ - break; - case 'L': - if (argc == 0) - goto usage; - ++argv, --argc; - Lpath(*argv); - break; - case 'u': - if (argc == 0) - goto usage; - ++argv, --argc; - lookup(*argv, INSTALL); - break; - case 'o': - if (argc == 0) - goto usage; - ++argv, --argc; - output = *argv; - break; - case 'e': - if (argc == 0) - goto usage; - ++argv, --argc; - entry = *argv; - break; - case 'D': - if (argc == 0) - goto usage; - ++argv, --argc; - datasiz = *argv; - break; - default: - usage: - usage(); - } - } - } - - if (argc == 0) - usage(); - - atexit(cleanup); - - pass1(argc, argv); - pass2(argc, argv); - - done = 1; - - return 0; -} diff --git a/ld/obj.c b/ld/obj.c @@ -1,153 +0,0 @@ -static char sccsid[] = "@(#) ./ld/obj.c"; - -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "../inc/scc.h" -#include "ld.h" - -#define NR_SYM_HASH 64 - -TUINT tsize, dsize, bsize; - -Obj *objlst; -static Obj *objtail; - -long numsects, numsymbols; -static Symbol *secttail; -static Symbol *symtbl[NR_SYM_HASH]; - -Section *sectlst; - -Obj * -add(Obj *obj) -{ - obj->next = NULL; - - if (!objlst) { - objtail = objlst = obj; - } else { - objtail->next = obj; - objtail = obj; - } -} - -void -delobj(Obj *obj) -{ - free(obj->strtbl); - free(obj->scnhdr); - free(obj->filhdr); - free(obj->fname); - free(obj->member); - free(obj); -} - -Obj * -newobj(char *fname, char *member, FILE *fp) -{ - Obj *obj; - char *s, *t; - size_t len; - - len = strlen(fname); - obj = malloc(sizeof(*obj)); - s = malloc(len) + 1; - if (!obj || !s) - outmem(); - memset(obj, 0, sizeof(*obj)); - obj->fname = memcpy(s, fname, len); - - if (!member) { - obj->member = NULL; - } else { - len = strlen(member) + 1; - if ((s = malloc(len)) == NULL) - outmem(); - obj->member = memcpy(s, member, len); - } - - obj->fp = fp; - if ((obj->offset = ftell(fp)) == EOF) { - fprintf(stderr, "ld: %s: %s\n", fname, strerror(errno)); - exit(1); - } - - return obj; -} - -Section * -slookup(char *name) -{ - char *s; - Section *prev, *sp; - size_t len = strlen(name); - - for (prev = sp = sectlst; sp; prev = sp, sp = sp->next) { - if (!memcmp(sp->name, name, len)) - return sp; - } - - sp = malloc(sizeof(*sp)); - s = malloc(len); - if (!sp || !s) - outmem(); - sp->name = s; - sp->base = 0; - sp->size = 0; - sp->next = NULL; - - if (!prev) - sectlst = sp; - else - prev->next = sp; - numsects++; - - return sp; -} - -static unsigned -hash(char *s) -{ - unsigned h, c; - - for (h = 0; c = *s; ++s) - h = h*33 ^ c; - return h & NR_SYM_HASH-1; -} - -Symbol * -lookup(char *name, int install) -{ - unsigned h; - char *s; - size_t len; - Symbol *sym; - - h = hash(name); - for (sym = symtbl[h]; sym; sym = sym->hash) { - s = sym->name; - if (*name == *s && !strcmp(name, s)) - return sym; - } - - if (!install) - return NULL; - - len = strlen(name) + 1; - sym = malloc(sizeof(*sym)); - s = malloc(len); - if (!sym || !s) - outmem(); - memset(sym, 0, sizeof(*sym)); - memcpy(s, name, len); - - sym->hash = symtbl[h]; - symtbl[h] = sym; - sym->name = s; - numsymbols++; - - return sym; -} diff --git a/lib/Makefile b/lib/Makefile @@ -1,15 +0,0 @@ -.POSIX: - -PROJECTDIR = .. - -include $(PROJECTDIR)/rules.mk - -DIRS = scc coff32 crt c - -all: $(DIRS) - -$(DIRS): FORCE - +@cd $@ && $(MAKE) - -dep clean distclean: - $(FORALL) diff --git a/lib/c/Makefile b/lib/c/Makefile @@ -1,29 +0,0 @@ -.POSIX: -PROJECTDIR =../.. -include $(PROJECTDIR)/scripts/rules.mk - -TARGET = $(PROJECTDIR)/lib/libc.a -DIRS = arch\ - assert\ - ctype\ - locale\ - stdio\ - stdlib\ - string\ - time\ - -all: $(DIRS) - +@$(MAKE) $(TARGET) - -$(DIRS): FORCE - +@cd $@ && $(MAKE) - -objlst: FORCE - ./mklst $(TARGET) - -$(TARGET): objlst - xargs $(AR) $(ARFLAGS) $@ < objlst - -clean: - $(FORALL) - rm -f objlst diff --git a/lib/c/arch/arm32/linux/time.c b/lib/c/arch/arm32/linux/time.c @@ -1 +0,0 @@ -#include "../../posix/time.c" diff --git a/lib/c/arch/arm32/longjmp.s b/lib/c/arch/arm32/longjmp.s @@ -1,11 +0,0 @@ - .file "longjmp.s" - - .text - .globl longjmp -longjmp: - ldmia r0, {r4-r11, sp, lr} - - // If r1 is 0 return 1 instead - movs r0, r1 - moveq r0, #1 - bx lr diff --git a/lib/c/arch/arm32/setjmp.s b/lib/c/arch/arm32/setjmp.s @@ -1,9 +0,0 @@ - .file "setjmp.s" - - .text - .globl setjmp -setjmp: - // IHI0042F_aapcs.pdf 5.1.1 callee saved registers - stmia r0, {r4-r11, sp, lr} - mov r0, #0 - bx lr diff --git a/lib/c/arch/arm64/Makefile b/lib/c/arch/arm64/Makefile @@ -1,14 +0,0 @@ -.POSIX: -PROJECTDIR =../../../.. -include $(PROJECTDIR)/scripts/rules.mk - -OBJS = longjmp.o setjmp.o -DIRS = linux - -all: $(OBJS) $(SYS) - -$(SYS): FORCE - +@cd $@ && $(MAKE) - -clean: - $(FORALL) diff --git a/lib/c/arch/arm64/linux/.gitignore b/lib/c/arch/arm64/linux/.gitignore @@ -1,10 +0,0 @@ -_Exit.s -_brk.s -_close.s -_getpid.s -_kill.s -_lseek.s -_openat.s -_read.s -_sys_errlist.c -_write.s diff --git a/lib/c/arch/arm64/linux/Makefile b/lib/c/arch/arm64/linux/Makefile @@ -1,37 +0,0 @@ -.POSIX: -PROJECTDIR =../../../../.. -include $(PROJECTDIR)/scripts/rules.mk -include ../../rules.mk - -OBJS = _Exit.o \ - _close.o \ - _brk.o \ - _getpid.o \ - _kill.o \ - _lseek.o \ - _openat.o \ - _read.o \ - _write.o \ - _getheap.o \ - _cerrno.o \ - _open.o \ - _sigaction.o \ - _tzone.o \ - getenv.o \ - raise.o \ - signal.o \ - time.o \ - _sys_errlist.o \ - -all: syscall - $(MAKE) objs - -objs: $(OBJS) - -syscall: syscall.lst - ./gensys.sh syscall.lst - touch syscall - -clean: - rm -f `awk '/[0-9]* _/ {print $$2".s"}' syscall.lst` - rm -f syscall _sys_errlist.c diff --git a/lib/c/arch/arm64/linux/_cerrno.s b/lib/c/arch/arm64/linux/_cerrno.s @@ -1,13 +0,0 @@ - .file "_cerrno.s" - .globl _cerrno - -_cerrno: - cmp x0,#0 - b.lt 1f - ret - -1: neg x0,x0 - adr x1,errno - str w0,[x1] - mov x0,#-1 - ret diff --git a/lib/c/arch/arm64/linux/_getheap.s b/lib/c/arch/arm64/linux/_getheap.s @@ -1,6 +0,0 @@ - .file "_getheap.s" - - .globl _getheap -_getheap: - mov x0,#0 - b _brk diff --git a/lib/c/arch/arm64/linux/_open.c b/lib/c/arch/arm64/linux/_open.c @@ -1,13 +0,0 @@ -#include <stddef.h> - -#include "../../../syscall.h" - -#define AT_FDCWD -100 - -extern int _openat(int fd, const char *fname, int flags); - -int -_open(const char *fname, int flags) -{ - return _openat(AT_FDCWD, fname, flags); -} diff --git a/lib/c/arch/arm64/linux/_sigaction.c b/lib/c/arch/arm64/linux/_sigaction.c @@ -1,14 +0,0 @@ -#include <stddef.h> -#include <sys.h> - -extern int _sigaction2(int sig, - struct sigaction *new, struct sigaction *old, - int siginfo[], int num); - -int -_sigaction(int sig, struct sigaction *new, struct sigaction *old) -{ - extern int _setcontext[]; - - return _sigaction2(sig, new, old, _setcontext, 2); -} diff --git a/lib/c/arch/arm64/linux/_tzone.c b/lib/c/arch/arm64/linux/_tzone.c @@ -1 +0,0 @@ -#include "../../posix/_tzone.c" diff --git a/lib/c/arch/arm64/linux/gensys.sh b/lib/c/arch/arm64/linux/gensys.sh @@ -1,21 +0,0 @@ -#!/bin/sh - -# -# This job is very easy because app and kernel ABI are identical -# until the 4th parameter, so we only have to set the syscall -# number in rax - -sed 's/[ ]*#.*// - /^$/d' syscall.lst | -while read num name -do -cat <<EOF > $name.s - .file "$name.s" - - .globl $name -$name: - mov x8,#$num - svc 0 - b _cerrno -EOF -done diff --git a/lib/c/arch/arm64/linux/getenv.c b/lib/c/arch/arm64/linux/getenv.c @@ -1 +0,0 @@ -#include "../../posix/getenv.c" diff --git a/lib/c/arch/arm64/linux/raise.c b/lib/c/arch/arm64/linux/raise.c @@ -1 +0,0 @@ -#include "../../posix/raise.c" diff --git a/lib/c/arch/arm64/linux/signal.c b/lib/c/arch/arm64/linux/signal.c @@ -1 +0,0 @@ -#include "../../posix/signal.c" diff --git a/lib/c/arch/arm64/linux/syscall.lst b/lib/c/arch/arm64/linux/syscall.lst @@ -1,11 +0,0 @@ -#number name -56 _openat -57 _close -63 _read -64 _write -93 _Exit -172 _getpid -129 _kill -62 _lseek -134 _sigaction -214 _brk diff --git a/lib/c/arch/arm64/linux/time.c b/lib/c/arch/arm64/linux/time.c @@ -1 +0,0 @@ -#include "../../posix/time.c" diff --git a/lib/c/arch/arm64/longjmp.s b/lib/c/arch/arm64/longjmp.s @@ -1,22 +0,0 @@ - .file "longjmp.s" - - .text - .globl longjmp -longjmp: - ldp x19, x20, [x0,#0] - ldp x21, x22, [x0,#16] - ldp x23, x24, [x0,#32] - ldp x25, x26, [x0,#48] - ldp x27, x28, [x0,#64] - ldp x29, x30, [x0,#80] - ldr x2, [x0,#104] - mov sp, x2 - ldp d8 , d9, [x0,#112] - ldp d10, d11, [x0,#128] - ldp d12, d13, [x0,#144] - ldp d14, d15, [x0,#160] - - mov x0, x1 - cbnz x1, 1f - mov x0, #1 -1: br x30 diff --git a/lib/c/arch/arm64/setjmp.s b/lib/c/arch/arm64/setjmp.s @@ -1,20 +0,0 @@ - .file "setjmp.s" - - .text - .globl setjmp -setjmp: - // IHI0055B_aapcs64.pdf 5.1.1, 5.1.2 callee saved registers - stp x19, x20, [x0,#0] - stp x21, x22, [x0,#16] - stp x23, x24, [x0,#32] - stp x25, x26, [x0,#48] - stp x27, x28, [x0,#64] - stp x29, x30, [x0,#80] - mov x2, sp - str x2, [x0,#104] - stp d8, d9, [x0,#112] - stp d10, d11, [x0,#128] - stp d12, d13, [x0,#144] - stp d14, d15, [x0,#160] - mov x0, #0 - ret diff --git a/lib/c/arch/generrno.sh b/lib/c/arch/generrno.sh @@ -1,35 +0,0 @@ -#!/bin/sh - -trap 'r=$?; rm -f $$.tmp; exit $r' EXIT HUP QUIT INT TERM - -for i -do - case $i in - -o) - out=$2 - shift 2 - ;; - --) - shift - break - ;; - -*) - echo usage: generrno.sh [-o output] file ... - exit 1 - ;; - *) - break - ;; - esac -done - -awk ' -/^E/ && $2 > 0 { - errno[$1] = $2 -} - -END { - for (i in errno) - print "#define", i, errno[i] | "sort -n -k3" - close("sort -n -k3") -}' $@ > $$.tmp && mv $$.tmp ${out:-errno.h} diff --git a/lib/c/arch/generrstr.sh b/lib/c/arch/generrstr.sh @@ -1,23 +0,0 @@ -#!/bin/sh - -trap 'r=$?; rm -f $$.tmp; exit $r' EXIT HUP INT QUIT TERM - -awk ' -/^E/ && $2 > 0 { - str = "" - for (i = 3; i <= NF; i++) - str = str " " $i - sub(/^ /, "", str) - errstr[$1] = str - if ($2 > max) - max = $2; -} - -END { - print "#include <errno.h>\n" - print "char *_sys_errlist[] = {" - for (i in errstr) - printf "\t%-20.20s = \"%s\",\n", "[" i "]", errstr[i] - print "};" - print "int _sys_nerr =", $2 + 1 ";" -}' $@ > $$.tmp && mv $$.tmp _sys_errlist.c diff --git a/lib/c/arch/mkerrstr b/lib/c/arch/mkerrstr @@ -1,24 +0,0 @@ -#!/bin/sh - -trap 'r=$?; rm -f $$.tmp; exit $r' EXIT HUP INT QUIT TERM - -awk ' -/^#define[ \t]*E/{ - str = "" - for (i = 5; i < NF; i++) - str = str " " $i - sub(/^ /, "", str) - errstr[$2] = str - if ($3 > max) - max = $3; -} - -END { - print "#include <errno.h>\n" - print "char *const _sys_errlist[] = {" - for (i in errstr) - printf "\t%-20.20s = \"%s\",\n", "[" i "]", errstr[i] - - print "};" - print "const int _sys_nerr =", max";" -}' $@ > $$.tmp && mv $$.tmp _sys_errlist.c diff --git a/lib/c/arch/posix/_tzone.c b/lib/c/arch/posix/_tzone.c @@ -1,27 +0,0 @@ -#include <stdlib.h> -#include <time.h> -#include "../../libc.h" - -struct tzone * -_tzone(struct tm *tm) -{ - static struct tzone tz; - static int first = 1; - - if (!first) - return &tz; - - tz.name = getenv("TZ"); - if (!tz.name || *tz.name == '\0') { - tz.name = NULL; - tz.gmtoff = 0; - tz.isdst = 0; - } else { - /* TODO: parse TZ string */ - tz.gmtoff = 0; - tz.isdst = 0; - } - first = 0; - - return &tz; -} diff --git a/lib/c/arch/posix/getenv.c b/lib/c/arch/posix/getenv.c @@ -1,18 +0,0 @@ -#include <stdlib.h> -#include <string.h> -#undef getenv - -extern char **_environ; - -char * -getenv(const char *name) -{ - char **p, *s; - size_t len = strlen(name); - - for (p = _environ; s = *p; ++p) { - if (!strncmp(name, s, len) && s[len] == '=') - return s + len + 1; - } - return NULL; -} diff --git a/lib/c/arch/posix/geterrno.sh b/lib/c/arch/posix/geterrno.sh @@ -1,8 +0,0 @@ -#!/bin/sh - -awk '/define[ ]*E/ && $3 ~ /[0-9]+/ && $3 > 0 { - sub(/\#define[ ]*/, "") - sub(/\/\*/, "") - sub(/\*\//, "") - print -}' /usr/include/sys/errno.h diff --git a/lib/c/arch/posix/raise.c b/lib/c/arch/posix/raise.c @@ -1,11 +0,0 @@ -#include <stddef.h> -#include <signal.h> -#include <sys.h> - -#undef raise - -int -raise(int signum) -{ - return _kill(_getpid(), signum); -} diff --git a/lib/c/arch/posix/signal.c b/lib/c/arch/posix/signal.c @@ -1,17 +0,0 @@ -#include <stddef.h> -#include <signal.h> -#include <sys.h> -#undef signal - -void -(*signal(int signum, void (*func)(int)))(int) -{ - struct sigaction sa = { - .sa_handler = func, - }; - - if (_sigaction(signum, &sa, &sa) < 0) - return SIG_ERR; - - return sa.sa_handler; -} diff --git a/lib/c/arch/posix/time.c b/lib/c/arch/posix/time.c @@ -1,21 +0,0 @@ -#include <time.h> - -struct timeval { - time_t tv_sec; - int tv_usec; /* TODO use a arch type */ -}; - -int -_gettimeofday(struct timeval * restrict tp, void * restrict tzp); - -time_t -time(time_t *t) -{ - struct timeval tv; - - if (_gettimeofday(&tv, NULL) == -1) - return -1; - if (t) - *t =tv.tv_sec; - return tv.tv_sec; -} diff --git a/lib/c/arch/rules.mk b/lib/c/arch/rules.mk @@ -1,4 +0,0 @@ -SYSERRNO = $(INCDIR)/bits/$(SYS)/sys/errno.h - -_sys_errlist.c: $(SYSERRNO) - ../../mkerrstr $(SYSERRNO) diff --git a/lib/c/assert/Makefile b/lib/c/assert/Makefile @@ -1,10 +0,0 @@ -.POSIX: -PROJECTDIR =../../.. -include $(PROJECTDIR)/scripts/rules.mk - -MORECFLAGS = -w - -OBJS = __assert.o\ - assert.o\ - -all: $(OBJS) diff --git a/lib/c/assert/__assert.c b/lib/c/assert/__assert.c @@ -1,9 +0,0 @@ -#include <assert.h> -#include <stdlib.h> -#include <stdio.h> - -void __assert(char *exp, char *file, long line) -{ - fprintf(stderr, "%s:%ld: assertion failed '%s'\n", file, line, exp); - abort(); -} diff --git a/lib/c/assert/assert.c b/lib/c/assert/assert.c @@ -1,13 +0,0 @@ -#include <assert.h> -#include <stdlib.h> -#include <stdio.h> -#undef assert - -void -assert(int exp) -{ - if (exp) - return; - fputs("assert failed\n", stderr); - abort(); -} diff --git a/lib/c/ctype/Makefile b/lib/c/ctype/Makefile @@ -1,24 +0,0 @@ -.POSIX: -PROJECTDIR =../../.. -include $(PROJECTDIR)/scripts/rules.mk - -MORECFLAGS = -w - -OBJS = ctype.o\ - isalnum.o\ - isalpha.o\ - isascii.o\ - isblank.o\ - iscntrl.o\ - isdigit.o\ - isgraph.o\ - islower.o\ - isprint.o\ - ispunct.o\ - isspace.o\ - isupper.o\ - isxdigit.o\ - tolower.o\ - toupper.o\ - -all: $(OBJS) diff --git a/lib/c/ctype/ctype.c b/lib/c/ctype/ctype.c @@ -1,22 +0,0 @@ -#include <ctype.h> - -/* __ctype is shifted by one to match EOF */ -const unsigned char __ctype[257] = { - 0, /* EOF */ - _C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */ - _C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */ - _C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */ - _C,_C,_C,_C,_C,_C,_C,_C, /* 24-31 */ - _S|_SP,_P,_P,_P,_P,_P,_P,_P, /* 32-39 */ - _P,_P,_P,_P,_P,_P,_P,_P, /* 40-47 */ - _D,_D,_D,_D,_D,_D,_D,_D, /* 48-55 */ - _D,_D,_P,_P,_P,_P,_P,_P, /* 56-63 */ - _P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */ - _U,_U,_U,_U,_U,_U,_U,_U, /* 72-79 */ - _U,_U,_U,_U,_U,_U,_U,_U, /* 80-87 */ - _U,_U,_U,_P,_P,_P,_P,_P, /* 88-95 */ - _P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */ - _L,_L,_L,_L,_L,_L,_L,_L, /* 104-111 */ - _L,_L,_L,_L,_L,_L,_L,_L, /* 112-119 */ - _L,_L,_L,_P,_P,_P,_P,_C, /* 120-127 */ -}; diff --git a/lib/c/ctype/isalnum.c b/lib/c/ctype/isalnum.c @@ -1,8 +0,0 @@ -#include <ctype.h> -#undef isalnum - -int -isalnum(int c) -{ - return (__ctype+1)[c] & (_U|_L|_D); -} diff --git a/lib/c/ctype/isalpha.c b/lib/c/ctype/isalpha.c @@ -1,8 +0,0 @@ -#include <ctype.h> -#undef isalpha - -int -isalpha(int c) -{ - return (__ctype+1)[c] & (_U|_L); -} diff --git a/lib/c/ctype/isascii.c b/lib/c/ctype/isascii.c @@ -1,8 +0,0 @@ -#include <ctype.h> -#undef isascii - -int -isascii(int c) -{ - return c <= 0x7f; -} diff --git a/lib/c/ctype/isblank.c b/lib/c/ctype/isblank.c @@ -1,7 +0,0 @@ -#include <ctype.h> - -int -isblank(int c) -{ - return (c == ' ') || (c == '\t'); -} diff --git a/lib/c/ctype/iscntrl.c b/lib/c/ctype/iscntrl.c @@ -1,8 +0,0 @@ -#include <ctype.h> -#undef iscntrl - -int -iscntrl(int c) -{ - return (__ctype+1)[c] & (_C); -} diff --git a/lib/c/ctype/isdigit.c b/lib/c/ctype/isdigit.c @@ -1,8 +0,0 @@ -#include <ctype.h> -#undef isdigit - -int -isdigit(int c) -{ - return (__ctype+1)[c] & (_D); -} diff --git a/lib/c/ctype/isgraph.c b/lib/c/ctype/isgraph.c @@ -1,8 +0,0 @@ -#include <ctype.h> -#undef isgraph - -int -isgraph(int c) -{ - return (__ctype+1)[c] & (_P|_U|_L|_D); -} diff --git a/lib/c/ctype/islower.c b/lib/c/ctype/islower.c @@ -1,8 +0,0 @@ -#include <ctype.h> -#undef islower - -int -islower(int c) -{ - return (__ctype+1)[c] & _L; -} diff --git a/lib/c/ctype/isprint.c b/lib/c/ctype/isprint.c @@ -1,8 +0,0 @@ -#include <ctype.h> -#undef isprint - -int -isprint(int c) -{ - return (__ctype+1)[c] & (_P|_U|_L|_D|_SP); -} diff --git a/lib/c/ctype/ispunct.c b/lib/c/ctype/ispunct.c @@ -1,8 +0,0 @@ -#include <ctype.h> -#undef ispunct - -int -ispunct(int c) -{ - return (__ctype+1)[c] & (_P); -} diff --git a/lib/c/ctype/isspace.c b/lib/c/ctype/isspace.c @@ -1,8 +0,0 @@ -#include <ctype.h> -#undef isspace - -int -isspace(int c) -{ - return (__ctype+1)[c] & _S; -} diff --git a/lib/c/ctype/isupper.c b/lib/c/ctype/isupper.c @@ -1,8 +0,0 @@ -#include <ctype.h> -#undef isupper - -int -isupper(int c) -{ - return (__ctype+1)[c] & _U; -} diff --git a/lib/c/ctype/isxdigit.c b/lib/c/ctype/isxdigit.c @@ -1,8 +0,0 @@ -#include <ctype.h> -#undef isxdigit - -int -isxdigit(int c) -{ - return (__ctype+1)[c] & (_D|_X); -} diff --git a/lib/c/ctype/tolower.c b/lib/c/ctype/tolower.c @@ -1,9 +0,0 @@ -#define __USE_MACROS -#include <ctype.h> -#undef tolower - -int -tolower(int c) -{ - return (isupper(c)) ? c | 0x20 : c; -} diff --git a/lib/c/ctype/toupper.c b/lib/c/ctype/toupper.c @@ -1,8 +0,0 @@ -#include <ctype.h> -#undef toupper - -int -toupper(int c) -{ - return (islower(c)) ? c & ~0x20 : c; -} diff --git a/lib/c/libc.h b/lib/c/libc.h @@ -1,42 +0,0 @@ -#define SUN 0 -#define MON 1 -#define TUE 2 -#define WED 3 -#define THU 4 -#define FRI 5 -#define SAT 6 - -#define JAN 0 -#define FEB 1 -#define DEC 11 - -#define EPOCH 1970 -#define FEBDAYS(y) ((_daysyear(y) == 366) ? 29 : 28) -#define SECMIN 60 -#define SECHOUR (60 * SECMIN) /* 3600 */ -#define SECDAY (24 * SECHOUR) /* 86400 */ - -#ifdef stdin -extern FILE *_fpopen(const char * restrict fname, - const char * restrict mode, - FILE * restrict fp); -#endif - -struct tzone { - char *name; - int gmtoff; - int isdst; -}; - -struct tm; - -extern struct tzone *_tzone(struct tm *tm); -extern int _daysyear(int year); -extern int _newyear(int year); -extern void *_getheap(void); -#ifdef FILE -extern int _flsbuf(FILE *fp); -extern void _allocbuf(FILE *fp); -#endif - -extern int _daysmon[12]; diff --git a/lib/c/locale/Makefile b/lib/c/locale/Makefile @@ -1,10 +0,0 @@ -.POSIX: -PROJECTDIR =../../.. -include $(PROJECTDIR)/scripts/rules.mk - -MORECFLAGS = -w - -OBJS = localeconv.o\ - setlocale.o\ - -all: $(OBJS) diff --git a/lib/c/locale/localeconv.c b/lib/c/locale/localeconv.c @@ -1,29 +0,0 @@ -#include <locale.h> -#include <limits.h> -#undef localeconv - -struct lconv * -localeconv(void) -{ - static struct lconv lc = { - .decimal_point = ".", - .thousands_sep = "", - .grouping = "", - .mon_decimal_point = "", - .mon_thousands_sep = "", - .mon_grouping = "", - .positive_sign = "", - .negative_sign = "", - .currency_symbol = "", - .int_curr_symbol = "", - .frac_digits = CHAR_MAX, - .p_cs_precedes = CHAR_MAX, - .n_cs_precedes = CHAR_MAX, - .p_sep_by_space = CHAR_MAX, - .p_sign_posn = CHAR_MAX, - .n_sep_by_space = CHAR_MAX, - .n_sign_posn = CHAR_MAX, - .int_frac_digits = CHAR_MAX, - }; - return &lc; -} diff --git a/lib/c/locale/setlocale.c b/lib/c/locale/setlocale.c @@ -1,16 +0,0 @@ -#include <locale.h> -#include <stddef.h> -#undef setlocale - -char * -setlocale(int category, const char *locale) -{ - if (category > LC_TIME || category < LC_ALL) - return NULL; - if (!locale || - locale[0] == '\0' || - locale[0] == 'C' && locale[1] == '\0') { - return "C"; - } - return NULL; -} diff --git a/lib/c/mklst b/lib/c/mklst @@ -1,12 +0,0 @@ -#!/bin/sh - -set -e -trap 'r=$?;rm -f $$.tmp;exit $r' EXIT HUP QUIT INT TERM -archive=${1?'First parameter must be the archive name'} - -if test -f $archive -then - newer="-newer $archive" -fi - -find . -name '*.o' $newer > $$.tmp && mv $$.tmp objlst diff --git a/lib/c/stdio/Makefile b/lib/c/stdio/Makefile @@ -1,47 +0,0 @@ -.POSIX: -PROJECTDIR =../../.. -include $(PROJECTDIR)/scripts/rules.mk - -MORECFLAGS = -w - -OBJS = __getc.o\ - __putc.o\ - _flsbuf.o\ - _fpopen.o\ - clearerr.o\ - fclose.o\ - feof.o\ - ferror.o\ - fgetc.o\ - fgets.o\ - fopen.o\ - fprintf.o\ - fputc.o\ - fputs.o\ - fread.o\ - freopen.o\ - fseek.o\ - ftell.o\ - fwrite.o\ - getc.o\ - getchar.o\ - gets.o\ - perror.o\ - printf.o\ - putc.o\ - putchar.o\ - puts.o\ - rewind.o\ - setbuf.o\ - setvbuf.o\ - snprintf.o\ - sprintf.o\ - __iob.o\ - tmpnam.o\ - vfprintf.o\ - vsnprintf.o\ - vsprintf.o\ - vprintf.o\ - _allocbuf.o\ - -all: $(OBJS) diff --git a/lib/c/stdio/__getc.c b/lib/c/stdio/__getc.c @@ -1,39 +0,0 @@ -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include "../libc.h" -#include "../syscall.h" - -int -__getc(FILE *fp) -{ - int cnt; - - if (fp->flags & (_IOEOF | _IOERR)) - return EOF; - - if ((fp->flags & (_IOREAD | _IORW)) == 0) { - fp->flags |= _IOERR; - errno = EBADF; - return EOF; - } - - if (fp->flags & _IOSTRG) { - fp->flags |= _IOEOF; - return EOF; - } - - if (fp->buf == NULL && _allocbuf(fp)) - return EOF; - - if ((cnt = _read(fp->fd, fp->buf, fp->len)) <= 0) { - fp->flags |= (cnt == 0) ? _IOEOF : _IOERR; - return EOF; - } - - fp->flags |= _IOREAD; - fp->rp = fp->buf; - fp->wp = fp->buf + cnt; - - return *fp->rp++; -} diff --git a/lib/c/stdio/__iob.c b/lib/c/stdio/__iob.c @@ -1,20 +0,0 @@ -#include <stdio.h> - -FILE __iob[FOPEN_MAX] = { - { - .fd = 0, - .flags = _IOREAD, - }, - { - .fd = 1, - .flags = _IOWRITE | _IOLBF, - }, - { - .fd = 2, - .buf = stderr->unbuf, - .len = sizeof(stderr->unbuf), - .flags = _IOWRITE | _IONBF, - .rp = stderr->unbuf, - .wp = stderr->unbuf, - }, -}; diff --git a/lib/c/stdio/__putc.c b/lib/c/stdio/__putc.c @@ -1,78 +0,0 @@ -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include "../libc.h" - -int -fflush(FILE *fp) -{ - int err; - - if (fp) - return _flsbuf(fp); - - err = 0; - for (fp = __iob; fp < &__iob[FOPEN_MAX]; ++fp) { - if ((fp->flags & _IOWRITE) == 0 && _flsbuf(fp)) - err = EOF; - } - return err; -} - -static void -cleanup(void) -{ - fflush(NULL); -} - -int -__putc(int ch, FILE *fp) -{ - static int first = 1; - - if (fp->flags & _IOERR) - return EOF; - - if (fp->flags & _IOREAD) { - fp->flags |= _IOERR; - errno = EBADF; - return EOF; - } - - if (fp->flags & _IOSTRG) { - fp->flags |= _IOERR; - return EOF; - } - - if (fp->buf == NULL && _allocbuf(fp)) - return EOF; - - if (first) { - if (atexit(cleanup)) { - fp->flags |= _IOERR; - errno = ENOMEM; - return EOF; - } - first = 0; - } - - if (fp->flags & _IOLBF) { - if (fp->wp == fp->lp && _flsbuf(fp)) - return EOF; - *fp->wp++ = ch; - if (ch == '\n' && _flsbuf(fp)) - return EOF; - } else if (fp->flags & _IOFBF) { - if (_flsbuf(fp)) - return EOF; - *fp->wp++ = ch; - fp->rp = fp->buf + fp->len; - } else { - *fp->wp++ = ch; - if (_flsbuf(fp)) - return EOF; - } - - fp->flags |= _IOWRITE; - return ch & 0xFF; -} diff --git a/lib/c/stdio/_allocbuf.c b/lib/c/stdio/_allocbuf.c @@ -1,21 +0,0 @@ -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include "../libc.h" - -int -_allocbuf(FILE *fp) -{ - char *bp; - - if ((bp = malloc(BUFSIZ)) == NULL) { - fp->flags |= _IOERR; - errno = ENOMEM; - return EOF; - } - fp->len = BUFSIZ; - fp->rp = fp->wp = fp->buf = bp; - fp->lp = bp + BUFSIZ; - - return 0; -} diff --git a/lib/c/stdio/_flsbuf.c b/lib/c/stdio/_flsbuf.c @@ -1,23 +0,0 @@ -#include <errno.h> -#include <stdio.h> - -#include "../libc.h" -#include "../syscall.h" - -int -_flsbuf(FILE *fp) -{ - size_t cnt; - - if (fp->flags&_IOREAD) - return 0; - - cnt = fp->wp - fp->buf; - if (cnt > 0 && _write(fp->fd, fp->buf, cnt) != cnt) { - fp->flags |= _IOERR; - return EOF; - } - fp->wp = fp->buf; - - return 0; -} diff --git a/lib/c/stdio/_fpopen.c b/lib/c/stdio/_fpopen.c @@ -1,75 +0,0 @@ -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <sys.h> -#include "../syscall.h" -#include "../libc.h" -#undef fopen - -FILE * -_fpopen(const char * restrict fname, - const char * restrict mode, - FILE * restrict fp) -{ - int i, flags, fd, rw, bin; - - flags = rw = bin = 0; - - if (mode[0] == '\0') - goto einval; - - for (i = 1; mode[i]; ++i) { - switch (mode[i]) { - case '+': - if (rw) - goto einval; - rw = 1; - break; - case 'b': - if (bin) - goto einval; - bin = 1; - break; - default: - goto einval; - } - } - - switch (mode[0]) { - case 'a': - flags |= O_APPEND | O_CREAT; - goto wrflags; - case 'w': - flags |= O_TRUNC | O_CREAT; - wrflags: - flags |= (rw) ? O_RDWR : O_WRONLY; - break; - case 'r': - flags = (rw) ? O_RDWR : O_RDONLY; - break; - default: - einval: - errno = EINVAL; - return NULL; - } - - if ((fd = _open(fname, flags)) < 0) - return NULL; - - fp->buf = NULL; - fp->fd = fd; - - if (!bin) - fp->flags |= _IOTXT; - - if (flags & O_RDWR) - fp->flags |= _IORW; - else if (flags & O_RDONLY) - fp->flags |= _IOREAD; - else - fp->flags |= _IOWRITE; - - fp->lp = fp->rp = fp->wp = NULL; - - return fp; -} diff --git a/lib/c/stdio/clearerr.c b/lib/c/stdio/clearerr.c @@ -1,8 +0,0 @@ -#include <stdio.h> -#undef clearerr - -void -clearerr(FILE *fp) -{ - fp->flags &= ~(_IOERR | _IOEOF); -} diff --git a/lib/c/stdio/fclose.c b/lib/c/stdio/fclose.c @@ -1,32 +0,0 @@ -#include <stdlib.h> -#include <stdio.h> -#include "../syscall.h" -#undef fclose - -int -fclose(FILE *fp) -{ - int r = EOF; - - if ((fp->flags & _IOSTRG) == 0 && - fp->flags & (_IOWRITE | _IOREAD | _IORW)) { - r = 0; - if (_flsbuf(fp) == EOF) - r = EOF; - if (_close(fp->fd) < 0) - r = EOF; - } - - if (fp->flags & _IOALLOC) { - free(fp->buf); - fp->buf = NULL; - } - - fp->flags &= ~(_IOWRITE | _IOREAD | _IORW | - _IOERR | _IOEOF | - _IOALLOC | - _IOTXT | - _IOSTRG); - - return r; -} diff --git a/lib/c/stdio/feof.c b/lib/c/stdio/feof.c @@ -1,8 +0,0 @@ -#include <stdio.h> -#undef feof - -int -feof(FILE *fp) -{ - return fp->flags & _IOEOF; -} diff --git a/lib/c/stdio/ferror.c b/lib/c/stdio/ferror.c @@ -1,8 +0,0 @@ -#include <stdio.h> -#undef ferror - -int -ferror(FILE *fp) -{ - return fp->flags & _IOERR; -} diff --git a/lib/c/stdio/fgetc.c b/lib/c/stdio/fgetc.c @@ -1,8 +0,0 @@ -#include <stdio.h> -#undef fgetc - -int -fgetc(FILE *fp) -{ - return getc(fp); -} diff --git a/lib/c/stdio/fgets.c b/lib/c/stdio/fgets.c @@ -1,19 +0,0 @@ -#include <stdio.h> -#undef fgets - -char * -fgets(char *s, int n, FILE *fp) -{ - int ch = 0; - char *t = s; - - while (--n > 0 && (ch = getc(fp)) != EOF) { - if ((*t++ = ch) == '\n') - break; - } - if (ch == EOF && s == t) - return NULL; - *t = '\0'; - - return s; -} diff --git a/lib/c/stdio/fopen.c b/lib/c/stdio/fopen.c @@ -1,23 +0,0 @@ -#include <errno.h> -#include <stdio.h> - -#include "../syscall.h" -#include "../libc.h" -#undef fopen - - -FILE * -fopen(const char * restrict name, const char * restrict mode) -{ - FILE *fp; - - for (fp = __iob; fp < &__iob[FOPEN_MAX]; ++fp) { - if ((fp->flags & (_IOREAD | _IOWRITE | _IORW)) == 0) - break; - } - if (fp == &__iob[FOPEN_MAX]) { - errno = ENOMEM; - return NULL; - } - return _fpopen(name, mode, fp); -} diff --git a/lib/c/stdio/fprintf.c b/lib/c/stdio/fprintf.c @@ -1,15 +0,0 @@ -#include <stdarg.h> -#include <stdio.h> -#undef fprintf - -int -fprintf(FILE * restrict fp, const char * restrict fmt, ...) -{ - va_list va; - int cnt; - - va_start(va, fmt); - cnt = vfprintf(fp, fmt, va); - va_end(va); - return cnt; -} diff --git a/lib/c/stdio/fputc.c b/lib/c/stdio/fputc.c @@ -1,8 +0,0 @@ -#include <stdio.h> -#undef fputc - -int -fputc(int c, FILE *fp) -{ - return putc(c, fp); -} diff --git a/lib/c/stdio/fputs.c b/lib/c/stdio/fputs.c @@ -1,12 +0,0 @@ -#include <stdio.h> -#undef fputs - -int -fputs(const char * restrict bp, FILE * restrict fp) -{ - int r, ch; - - while (ch = *bp++) - r = putc(ch, fp); - return r; -} diff --git a/lib/c/stdio/fread.c b/lib/c/stdio/fread.c @@ -1,25 +0,0 @@ -#include <stdio.h> -#undef fread - -size_t -fread(void * restrict ptr, size_t size, size_t nmemb, - FILE * restrict fp) -{ - unsigned char *bp = ptr; - size_t n, i; - int c; - - if (size == 0) - return 0; - - for (n = 0; n < nmemb; n++) { - i = size; - do { - if ((c = getc(fp)) == EOF) - return n; - *bp++ = c; - } while (--i); - } - - return n; -} diff --git a/lib/c/stdio/freopen.c b/lib/c/stdio/freopen.c @@ -1,14 +0,0 @@ -#include <stdio.h> - -#include "../syscall.h" -#include "../libc.h" -#undef freopen - -FILE * -freopen(const char * restrict name, const char * restrict mode, - FILE * restrict fp) -{ - if (fclose(fp) == EOF) - return NULL; - return _fpopen(name, mode, fp); -} diff --git a/lib/c/stdio/fseek.c b/lib/c/stdio/fseek.c @@ -1,26 +0,0 @@ -#include <stdio.h> -#include "../syscall.h" -#undef fseek - -int -fseek(FILE *fp, long off, int whence) -{ - if (fp->flags & _IOERR) - return EOF; - - if ((fp->flags & _IOWRITE) && _flsbuf(fp)) - return -1; - else if (whence == SEEK_CUR && (fp->flags & _IOREAD)) - off -= fp->wp - fp->rp; - - if (_lseek(fp->fd, off, whence) < 0) { - fp->flags |= _IOERR; - return EOF; - } - - if (fp->flags & _IORW) - fp->flags &= ~(_IOREAD | _IOWRITE); - fp->flags &= ~_IOEOF; - - return 0; -} diff --git a/lib/c/stdio/ftell.c b/lib/c/stdio/ftell.c @@ -1,27 +0,0 @@ -#include <stdio.h> -#include "../syscall.h" -#undef ftell - -long -ftell(FILE *fp) -{ - long off; - unsigned char *p; - - if (fp->flags & _IOERR) - return EOF; - - if ((off = _lseek(fp->fd, 0, SEEK_CUR)) < 0) { - fp->flags |= _IOERR; - return EOF; - } - - if (fp->flags & _IOREAD) - return off - (fp->wp - fp->rp); - - if (fp->flags & _IOWRITE) { - p = (fp->flags & _IOLBF) ? fp->lp : fp->wp; - return off + (p - fp->buf); - } - return off; -} diff --git a/lib/c/stdio/fwrite.c b/lib/c/stdio/fwrite.c @@ -1,24 +0,0 @@ -#include <stdio.h> -#undef fwrite - -size_t -fwrite(const void * restrict ptr, size_t size, size_t nmemb, - FILE * restrict fp) -{ - const unsigned char *bp = ptr; - size_t n, i; - - if (size == 0) - return 0; - - for (n = 0; n < nmemb; n++) { - i = size; - do - putc(*bp++, fp); - while (--i); - if (ferror(fp)) - break; - } - - return n; -} diff --git a/lib/c/stdio/getc.c b/lib/c/stdio/getc.c @@ -1,8 +0,0 @@ -#include <stdio.h> -#undef getc - -int -getc(FILE *fp) -{ - return (fp->rp >= fp->wp) ? __getc(fp) : *fp->rp++; -} diff --git a/lib/c/stdio/getchar.c b/lib/c/stdio/getchar.c @@ -1,8 +0,0 @@ -#include <stdio.h> -#undef getchar - -int -getchar(void) -{ - return getc(stdin); -} diff --git a/lib/c/stdio/gets.c b/lib/c/stdio/gets.c @@ -1,17 +0,0 @@ -#include <stdio.h> -#undef gets - -char * -gets(char *s) -{ - int ch; - char *t = s; - - while ((ch = getc(stdin)) != EOF && ch != '\n') - *t++ = ch; - if (ch == EOF && s == t) - return NULL; - *t = '\0'; - - return s; -} diff --git a/lib/c/stdio/perror.c b/lib/c/stdio/perror.c @@ -1,16 +0,0 @@ -#include <errno.h> -#include <stdio.h> -#include <string.h> -#undef perror - -void -perror(const char *msg) -{ - if (msg && *msg) { - fputs(msg, stderr); - putc(':', stderr); - putc(' ', stderr); - } - fputs(strerror(errno), stderr); - putc('\n', stderr); -} diff --git a/lib/c/stdio/printf.c b/lib/c/stdio/printf.c @@ -1,15 +0,0 @@ -#include <stdarg.h> -#include <stdio.h> -#undef printf - -int -printf(const char * restrict fmt, ...) -{ - int cnt; - va_list va; - - va_start(va, fmt); - cnt = vfprintf(stdout, fmt, va); - va_end(va); - return cnt; -} diff --git a/lib/c/stdio/putc.c b/lib/c/stdio/putc.c @@ -1,8 +0,0 @@ -#include <stdio.h> -#undef putc - -int -putc(int ch, FILE *fp) -{ - return (fp->wp >= fp->rp) ? __putc(ch,fp) : (*fp->wp++ = ch); -} diff --git a/lib/c/stdio/putchar.c b/lib/c/stdio/putchar.c @@ -1,8 +0,0 @@ -#include <stdio.h> -#undef putchar - -int -putchar(int ch) -{ - return putc(ch, stdout); -} diff --git a/lib/c/stdio/puts.c b/lib/c/stdio/puts.c @@ -1,12 +0,0 @@ -#include <stdio.h> -#undef puts - -int -puts(const char *str) -{ - int ch; - - while (ch = *str++) - putchar(ch); - return putchar('\n'); -} diff --git a/lib/c/stdio/rewind.c b/lib/c/stdio/rewind.c @@ -1,10 +0,0 @@ -#include <stdio.h> -#undef rewind - -void -rewind(FILE *fp) -{ - fp->flags &= ~_IOERR; - fseek(fp, 0, SEEK_SET); - clearerr(fp); -} diff --git a/lib/c/stdio/setbuf.c b/lib/c/stdio/setbuf.c @@ -1,8 +0,0 @@ -#include <stdio.h> -#undef setbuf - -void -setbuf(FILE * restrict fp, char * restrict buf) -{ - setvbuf(fp, buf, (buf) ? _IOFBF : _IONBF, BUFSIZ); -} diff --git a/lib/c/stdio/setvbuf.c b/lib/c/stdio/setvbuf.c @@ -1,48 +0,0 @@ -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#undef setvbuf - -int -setvbuf(FILE * restrict fp, char * restrict buf, int mode, size_t size) -{ - int flags; - char *p; - size_t l; - - if (_flsbuf(fp) == EOF) - return EOF; - - if (buf) - p = buf, l = size; - else - p = fp->buf, l = fp->len; - - switch (mode) { - case _IONBF: - l = sizeof(fp->unbuf); - p = fp->unbuf; - case _IOLBF: - case _IOFBF: - fp->rp = fp->wp = p; - fp->lp = p + l; - break; - default: - errno = EINVAL; - return EOF; - } - - flags = fp->flags; - if (flags&_IOALLOC && (buf || mode == _IONBF)) { - free(fp->buf); - flags &= ~_IOALLOC; - } - - fp->buf = p; - fp->len = l; - flags &= ~(_IONBF | _IOLBF | _IOFBF); - flags |= mode; - fp->flags = flags; - - return 0; -} diff --git a/lib/c/stdio/snprintf.c b/lib/c/stdio/snprintf.c @@ -1,16 +0,0 @@ -#include <stdarg.h> -#include <stdio.h> -#undef snprintf - -int -snprintf(char * restrict s, size_t siz, const char * restrict fmt, ...) -{ - int r; - va_list va; - - va_start(va, fmt); - r = vsnprintf(s, siz, fmt, va); - va_end(va); - - return r; -} diff --git a/lib/c/stdio/sprintf.c b/lib/c/stdio/sprintf.c @@ -1,16 +0,0 @@ -#include <stdarg.h> -#include <stdio.h> -#undef sprintf - -int -sprintf(char * restrict s, const char * restrict fmt, ...) -{ - int r; - - va_list va; - va_start(va, fmt); - r = vsprintf(s, fmt, va); - va_end(va); - - return r; -} diff --git a/lib/c/stdio/tmpnam.c b/lib/c/stdio/tmpnam.c @@ -1,31 +0,0 @@ -#include <stdio.h> -#include <string.h> -#include "../syscall.h" -#undef tmpnam - -char * -tmpnam(char *s) -{ - static char *tmpl, buf[L_tmpnam]; - char *p; - - if (*buf == '\0') { - for (tmpl = buf, p = _TMPNAME; *tmpl++ = *p++; ) - ; - for (p = tmpl; p < &buf[L_tmpnam-1]; ++p) - *p = '0'; - *p = '\0'; - } - for (;;) { - for (p = tmpl; *p && *p != '9'; ++p) - ; - if (*p == '\0') - return NULL; - ++*p; - if (_access(buf, 0) != 0) - break; - } - if (s) - strcpy(s, buf); - return buf; -} diff --git a/lib/c/stdio/vfprintf.c b/lib/c/stdio/vfprintf.c @@ -1,362 +0,0 @@ -#include <ctype.h> -#include <limits.h> -#include <stdarg.h> -#include <stdint.h> -#include <stdio.h> -#include <string.h> -#include <wchar.h> -#undef vfprintf - -enum { - LONG = 1 << 0, - LLONG = 1 << 1, - SHORT = 1 << 2, - CHAR = 1 << 3, - SIZET = 1 << 4, - PTRDIFF = 1 << 5, - INTMAX = 1 << 6, - VOIDPTR = 1 << 7, - UNSIGNED = 1 << 8, - ALTFORM = 1 << 9, -}; - -#define MAXPREC 50 - -struct conv { - int sign; - int prec; - char *digs; - int base; -}; - -static uintmax_t -getnum(va_list *va, int flags, int *sign) -{ - uintmax_t uval; - intmax_t val; - - if (flags & CHAR) { - val = va_arg(*va, int); - uval = (unsigned char) val; - } else if (flags & SHORT) { - val = va_arg(*va, int); - uval = (unsigned short) val; - } else if (flags & LONG) { - val = va_arg(*va, long); - uval = (unsigned long) val; - } else if (flags & LLONG) { - val = va_arg(*va, long long); - uval = (unsigned long long) val; - } else if (flags & SIZET) { - uval = va_arg(*va, size_t); - } else if (flags & INTMAX) { - val = va_arg(*va, intmax_t); - uval = (uintmax_t) val; - } else if (flags & VOIDPTR) { - uval = (uintmax_t) va_arg(*va, void *); - } else { - val = va_arg(*va, int); - uval = (unsigned) val; - } - - if ((flags & UNSIGNED) == 0 && val < 0) { - *sign = '-'; - uval = -uval; - } - return uval; -} - -static char * -numtostr(uintmax_t val, int flags, struct conv *conv, char *buf) -{ - char *buf0 = buf; - int base = conv->base, prec = conv->prec; - uintmax_t oval = val; - - if (prec == -1) - prec = 1; - - for (*buf = '\0'; val > 0; val /= base) - *--buf = conv->digs[val % base]; - while (buf0 - buf < prec) - *--buf = '0'; - - if (flags & ALTFORM) { - if (base == 8 && *buf != '0') { - *--buf = '0'; - } else if (base == 16 && oval != 0) { - *--buf = conv->digs[16]; - *--buf = '0'; - } - } - if (conv->sign) - *--buf = conv->sign; - - return buf; -} - -static void -savecnt(va_list *va, int flags, int cnt) -{ - if (flags & CHAR) - *va_arg(*va, char*) = cnt; - else if (flags & SHORT) - *va_arg(*va, short*) = cnt; - else if (flags & LONG) - *va_arg(*va, long*) = cnt; - else if (flags & LLONG) - *va_arg(*va, long long*) = cnt; - else if (flags & SIZET) - *va_arg(*va, size_t*) = cnt; - else if (flags & INTMAX) - *va_arg(*va, intmax_t*) = cnt; - else - *va_arg(*va, int*) = cnt; -} - -static size_t -wstrout(wchar_t *ws, size_t len, int width, int fill, FILE * restrict fp) -{ - int left = 0, adjust; - size_t cnt = 0; - wchar_t wc; -#if 0 - - if (width < 0) { - left = 1; - width = -width; - } - - len *= sizeof(wchar_t); - adjust = (len < width) ? width - len : 0; - cnt = adjust + len; - if (left) - adjust = -adjust; - - for ( ; adjust > 0; adjust++) - putc(fill, fp); - - while (wc = *ws++) - putwc(wc, fp); - - for ( ; adjust < 0; adjust--) - putc(' ', fp); -#endif - return cnt; -} - -static size_t -strout(char *s, size_t len, int width, int fill, FILE * restrict fp) -{ - int left = 0, adjust, ch, prefix; - size_t cnt = 0; - - if (width < 0) { - left = 1; - width = -width; - } - - adjust = (len < width) ? width - len : 0; - cnt = adjust + len; - if (left) - adjust = -adjust; - - if (fill == '0') { - if (*s == '-' || *s == '+') - prefix = 1; - else if (*s == '0' && toupper(s[1]) == 'X') - prefix = 2; - else - prefix = 0; - while (prefix--) { - putc(*s++, fp); - --len; - } - } - - for ( ; adjust > 0; adjust--) - putc(fill, fp); - - while (ch = *s++) - putc(ch, fp); - - for ( ; adjust < 0; adjust++) - putc(' ', fp); - - return cnt; -} - -int -vfprintf(FILE * restrict fp, const char *fmt, va_list va) -{ - int ch, n, flags, width, left, fill, cnt = 0; - size_t inc, len; - char *s; - wchar_t *ws; - struct conv conv; - char buf[MAXPREC+1]; - wchar_t wbuf[2]; - va_list va2; - - va_copy(va2, va); - for (cnt = 0; ch = *fmt++; cnt += inc) { - if (ch != '%') { - putc(ch, fp); - inc = 1; - continue; - } - - fill = ' '; - left = flags = width = 0; - conv.prec = -1; - conv.base = 10; - conv.sign = '\0'; - conv.digs = "0123456789ABCDEFX"; - -flags: - switch (*fmt++) { - case ' ': - if (conv.sign == '\0') - conv.sign = ' '; - goto flags; - case '+': - conv.sign = '+'; - goto flags; - case '#': - flags |= ALTFORM; - goto flags; - case '.': - if (*fmt == '*') { - fmt++; - n = va_arg(va2, int); - } else { - for (n = 0; isdigit(ch = *fmt); fmt++) - n = n * 10 + ch - '0'; - } - if (n > MAXPREC) - n = MAXPREC; - if (n > 0) - conv.prec = n; - goto flags; - case '*': - width = va_arg(va2, int); - goto flags; - case '-': - left = 1; - ++fmt; - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - --fmt; - for (n = 0; isdigit(ch = *fmt); ++fmt) - n = n * 10 + ch - '0'; - if (left) - n = -n; - width = n; - goto flags; - case '0': - fill = '0'; - goto flags; - case 'l': - flags += LONG; - goto flags; - case 'h': - flags += SHORT; - goto flags; - case '%': - ch = '%'; - goto cout; - case 'c': - if (flags & LONG) { - wbuf[0] = va_arg(va2, wint_t); - wbuf[1] = L'\0'; - ws = wbuf; - len = 1; - goto wstrout; - } - ch = va_arg(va2, int); - cout: - buf[0] = ch; - buf[1] = '\0'; - s = buf; - len = 1; - goto strout; - case 'j': - flags |= INTMAX; - goto flags; - case 't': - flags |= PTRDIFF; - goto flags; - case 'z': - flags |= SIZET; - goto flags; - case 'u': - flags |= UNSIGNED; - case 'i': - case 'd': - conv.base = 10; - goto numeric; - case 'p': - flags |= VOIDPTR | ALTFORM; - goto numeric16; - case 'x': - conv.digs = "0123456789abcdefx"; - case 'X': - numeric16: - conv.base = 16; - flags |= UNSIGNED; - goto numeric; - case 'o': - conv.base = 8; - flags |= UNSIGNED; - numeric: - if (conv.prec != -1) - fill = ' '; - s = numtostr(getnum(&va2, flags, &conv.sign), - flags, - &conv, - &buf[MAXPREC]); - len = &buf[MAXPREC] - s; - goto strout; - case 'L': - case 'a': - case 'A': - case 'e': - case 'E': - case 'f': - case 'g': - case 'G': - /* TODO */ - case 's': - if (flags & LONG) { - ws = va_arg(va2, wchar_t *); - /* len = wcsnlen(ws, conv.prec); */ - goto wstrout; - } else { - s = va_arg(va2, char *); - len = strnlen(s, conv.prec); - goto strout; - } - wstrout: - inc = wstrout(ws, len, width, fill, fp); - break; - strout: - inc = strout(s, len, width, fill, fp); - break; - case 'n': - savecnt(&va2, flags, cnt); - break; - case '\0': - goto out_loop; - } - } - -out_loop: - return (ferror(fp)) ? EOF : cnt; -} diff --git a/lib/c/stdio/vprintf.c b/lib/c/stdio/vprintf.c @@ -1,12 +0,0 @@ -#include <stdarg.h> -#include <stdio.h> -#undef vprintf - -int -vprintf(const char *fmt, va_list ap) -{ - va_list ap2; - - va_copy(ap2, ap); - return vfprintf(stdout, fmt, ap2); -} diff --git a/lib/c/stdio/vsnprintf.c b/lib/c/stdio/vsnprintf.c @@ -1,25 +0,0 @@ -#include <stdarg.h> -#include <stdio.h> -#undef vsnprintf - -int -vsnprintf(char * restrict s, size_t siz, const char * restrict fmt, va_list ap) -{ - FILE f; - int r; - - f.flags = _IORW | _IOSTRG; - f.len = siz; - f.buf = s; - f.wp = s; - f.rp = s + siz; - - r = vfprintf(&f, fmt, ap); - if (s) { - if (f.wp == f.rp) - --f.wp; - *f.wp = '\0'; - } - - return r; -} diff --git a/lib/c/stdio/vsprintf.c b/lib/c/stdio/vsprintf.c @@ -1,12 +0,0 @@ -#include <limits.h> -#include <stdarg.h> -#include <stdint.h> -#include <stdio.h> -#undef vsprintf - - -int -vsprintf(char * restrict s, const char * restrict fmt, va_list va) -{ - return vsnprintf(s, SIZE_MAX, fmt, va); -} diff --git a/lib/c/stdlib/Makefile b/lib/c/stdlib/Makefile @@ -1,25 +0,0 @@ -.POSIX: -PROJECTDIR =../../.. -include $(PROJECTDIR)/scripts/rules.mk - -MORECFLAGS = -w - -OBJS = abort.o\ - abs.o\ - atexit.o\ - atoi.o\ - atol.o\ - atoll.o\ - bsearch.o\ - calloc.o\ - errno.o\ - exit.o\ - labs.o\ - llabs.o\ - malloc.o\ - qsort.o\ - rand.o\ - realloc.o\ - strtoull.o\ - -all: $(OBJS) diff --git a/lib/c/stdlib/abort.c b/lib/c/stdlib/abort.c @@ -1,10 +0,0 @@ -#include <signal.h> -#include <stdlib.h> -#undef abort - -void -abort(void) -{ - raise(SIGABRT); - _Exit(127); -} diff --git a/lib/c/stdlib/abs.c b/lib/c/stdlib/abs.c @@ -1,8 +0,0 @@ -#include <stdlib.h> -#undef abs - -int -abs(int n) -{ - return (n < 0) ? -n : n; -} diff --git a/lib/c/stdlib/atexit.c b/lib/c/stdlib/atexit.c @@ -1,17 +0,0 @@ -#include <stdlib.h> -#include <errno.h> -#undef atexit - -extern void (*_exitf[_ATEXIT_MAX])(void); -extern unsigned _exitn; - -int -atexit(void (*fun)(void)) -{ - if (_exitn == _ATEXIT_MAX) { - errno = ENOMEM; - return -1; - } - _exitf[_exitn++] = fun; - return 0; -} diff --git a/lib/c/stdlib/atoi.c b/lib/c/stdlib/atoi.c @@ -1,25 +0,0 @@ -#include <ctype.h> -#include <stdlib.h> -#undef atoi - -int -atoi(const char *s) -{ - int n, sign = -1; - - while (isspace(*s)) - ++s; - - switch (*s) { - case '-': - sign = 1; - case '+': - ++s; - } - - /* Compute n as a negative number to avoid overflow on INT_MIN */ - for (n = 0; isdigit(*s); ++s) - n = 10*n - (*s - '0'); - - return sign * n; -} diff --git a/lib/c/stdlib/atol.c b/lib/c/stdlib/atol.c @@ -1,26 +0,0 @@ -#include <ctype.h> -#include <stdlib.h> -#undef atol - -long -atol(const char *s) -{ - int sign = -1; - long n; - - while (isspace(*s)) - ++s; - - switch (*s) { - case '-': - sign = 1; - case '+': - ++s; - } - - /* Compute n as a negative number to avoid overflow on LONG_MIN */ - for (n = 0; isdigit(*s); ++s) - n = 10*n - (*s - '0'); - - return sign * n; -} diff --git a/lib/c/stdlib/atoll.c b/lib/c/stdlib/atoll.c @@ -1,26 +0,0 @@ -#include <ctype.h> -#include <stdlib.h> -#undef atoll - -long long -atoll(const char *s) -{ - int sign = -1; - long long n; - - while (isspace(*s)) - ++s; - - switch (*s) { - case '-': - sign = 1; - case '+': - ++s; - } - - /* Compute n as a negative number to avoid overflow on LLONG_MIN */ - for (n = 0; isdigit(*s); ++s) - n = 10*n - (*s - '0'); - - return sign * n; -} diff --git a/lib/c/stdlib/bsearch.c b/lib/c/stdlib/bsearch.c @@ -1,26 +0,0 @@ -#include <stdlib.h> - -void * -bsearch(const void *key, const void *ary, size_t n, size_t size, - int (*cmp)(const void *, const void *)) -{ - int t; - size_t mid, low, high; - char *cur, *base = ary; - - low = 0; - high = n - 1; - while (low <= high) { - mid = low + (high - low) / 2; - cur = base + mid*size; - - if ((t = (*cmp)(key, cur)) == 0) - return cur; - else if (t > 0) - low = mid + 1; - else - high = mid - 1; - } - - return NULL; -} diff --git a/lib/c/stdlib/calloc.c b/lib/c/stdlib/calloc.c @@ -1,18 +0,0 @@ -#include <stdlib.h> -#include <string.h> -#undef calloc - -void * -calloc(size_t nmemb, size_t size) -{ - size_t nbytes; - void *mem; - - if (!nmemb || !size || nmemb > (size_t)-1/size) - return NULL; - - nbytes = nmemb * size; - if ((mem = malloc(nbytes)) == NULL) - return NULL; - return memset(mem, 0, nbytes); -} diff --git a/lib/c/stdlib/errno.c b/lib/c/stdlib/errno.c @@ -1 +0,0 @@ -int errno; diff --git a/lib/c/stdlib/exit.c b/lib/c/stdlib/exit.c @@ -1,13 +0,0 @@ -#include <stdlib.h> -#undef exit - -void (*_exitf[_ATEXIT_MAX])(void); -unsigned _exitn; - -void -exit(int status) -{ - while (_exitn > 0) - (*_exitf[--_exitn])(); - _Exit(status); -} diff --git a/lib/c/stdlib/labs.c b/lib/c/stdlib/labs.c @@ -1,8 +0,0 @@ -#include <stdlib.h> -#undef labs - -long -labs(long n) -{ - return (n < 0) ? -n : n; -} diff --git a/lib/c/stdlib/llabs.c b/lib/c/stdlib/llabs.c @@ -1,8 +0,0 @@ -#include <stdlib.h> -#undef llabs - -long long -llabs(long long n) -{ - return (n < 0) ? -n : n; -} diff --git a/lib/c/stdlib/malloc.c b/lib/c/stdlib/malloc.c @@ -1,158 +0,0 @@ -#include <errno.h> -#include <stdint.h> -#include <stdlib.h> -#include <string.h> - -#include "malloc.h" -#include "../syscall.h" - -#define MAXADDR ((char *)-1) -#define ERRADDR ((char *)-1) - -static Header base = { .h.next = &base }; -static Header *freep = &base; - -/* - * Run over the free list looking for the nearest previous - * block. There are two possible results: end of the list - * or an intermediary block. - */ -void * -_prevchunk(Header *hp) -{ - Header *p; - - for (p = freep; ;p = p->h.next) { - /* hp between p and p->h.next? */ - if (p < hp && hp < p->h.next) - break; - /* p before hp and hp at the end of list? */ - if (p->h.next <= p && (hp < p->h.next || hp > p)) - break; - } - return p; -} - -/* - * Get the previous block and try to merge - * with next and previous blocks - */ -void -free(void *mem) -{ - Header *hp, *prev; - - if (!mem) - return; - - hp = (Header *) mem - 1; - prev = _prevchunk(hp); - - /* join to next */ - if (hp + hp->h.size == prev->h.next) { - hp->h.size += prev->h.next->h.size; - hp->h.next = prev->h.next->h.next; - } else { - hp->h.next = prev->h.next; - } - - /* join to previous */ - if (prev + prev->h.size == hp) { - prev->h.size += hp->h.size; - prev->h.next = hp->h.next; - } else { - prev->h.next = hp; - } - - freep = prev; -} - -static void * -sbrk(uintptr_t inc) -{ - char *new, *old; - void *p; - static void *heap; - - if (!heap) - heap = _getheap(); - old = heap; - if (old >= MAXADDR - inc) - return ERRADDR; - new = old + inc; - p = _brk(new); - if (p == old || p < 0) - return ERRADDR; - heap = new; - - return old; -} - -static Header * -morecore(size_t nunits) -{ - char *rawmem; - Header *hp; - - if (nunits < NALLOC) - nunits = NALLOC; - - rawmem = sbrk(nunits * sizeof(Header)); - if (rawmem == ERRADDR) - return NULL; - - hp = (Header*)rawmem; - hp->h.size = nunits; - - /* integrate new memory into the list */ - free(hp + 1); - - return freep; -} - -/* - * Run over the list of free blocks trying to find a block - * big enough for nbytes. If the block fit perfectly with - * the required size then we only have to unlink - * the block. Otherwise we have to split the block and - * return the right part. If we run over the full list - * without a fit then we have to require more memory - * - * ______________________________________ - * ___________./______________________________________\_____ - * ...| in | | | in | |.....| in | | | |.... - * ...| use | | | use | |.....| use | | | |.... - * ___|______|___|.____|_____|._|_____|______|._|.___|.|____ - * \__/ \_________/ \_____________/ \/ \__/ - */ -void * -malloc(size_t nbytes) -{ - Header *cur, *prev; - size_t nunits; - - /* 1 unit for header plus enough units to fit nbytes */ - nunits = (nbytes+sizeof(Header)-1) / sizeof(Header) + 1; - - for (prev = freep; ; prev = cur) { - cur = prev->h.next; - if (cur->h.size >= nunits) { - if (cur->h.size == nunits) { - prev->h.next = cur->h.next; - } else { - cur->h.size -= nunits; - cur += cur->h.size; - cur->h.size = nunits; - } - freep = prev; - return cur + 1; - } - - if (cur == freep) { - if ((cur = morecore(nunits)) == NULL) { - errno = ENOMEM; - return NULL; - } - } - } -} diff --git a/lib/c/stdlib/malloc.h b/lib/c/stdlib/malloc.h @@ -1,16 +0,0 @@ -#include <stdlib.h> - -/* minimum amount of required units */ -#define NALLOC 10000 - -typedef union header Header; -union header { - struct hdr { - Header *next; - size_t size; - } h; - /* most restrictive type fixes the union size for alignment */ - _ALIGNTYPE most; -}; - -extern void *_prevchunk(Header *hp); diff --git a/lib/c/stdlib/qsort.c b/lib/c/stdlib/qsort.c @@ -1,68 +0,0 @@ -#include <stdlib.h> -#include <string.h> -#undef qsort - -/* - * This implementation of qsort is based in the paper - * "Engineering a Sort Function", by Jon L.Bentley and M. Douglas McIlroy. - * A lot of different optimizations were removed to make the code simpler. - */ - -struct qsort { - size_t es; - int (*cmp)(const void *, const void *); -}; - -static void -swap(char *i, char *j, size_t n) -{ - do { - char c = *i; - *i++ = *j; - *j++ = c; - } while (--n > 0); -} - -static void -xqsort(char *a, size_t n, struct qsort *qs) -{ - size_t j, es = qs->es; - char *pi, *pj, *pn; - - if (n <= 1) - return; - - pi = a; - pn = pj = a + n*es; - - swap(a, a + n/2 * es, es); - for (;;) { - do { - pi += es; - } while (pi < pn && qs->cmp(pi, a) < 0); - - do { - pj -= es; - } while (pj > a && qs->cmp(pj, a) > 0); - - if (pj < pi) - break; - swap(pi, pj, es); - } - swap(a, pj, es); - - j = (pj - a) / es; - xqsort(a, j, qs); - xqsort(a + (j+1)*es, n-j-1, qs); -} - -void -qsort(void *base, size_t nmemb, size_t size, - int (*f)(const void *, const void *)) -{ - struct qsort qs; - - qs.cmp = f; - qs.es = size; - xqsort(base, nmemb, &qs); -} diff --git a/lib/c/stdlib/rand.c b/lib/c/stdlib/rand.c @@ -1,18 +0,0 @@ -#include <stdlib.h> -#undef rand -#undef srand - -static unsigned long next; - -void -srand(unsigned seed) -{ - next = seed; -} - -int -rand(void) /* RAND_MAX assumed to be 32767. */ -{ - next = next * 1103515245 + 12345; - return (unsigned)(next/65536) % 32768; -} diff --git a/lib/c/stdlib/realloc.c b/lib/c/stdlib/realloc.c @@ -1,68 +0,0 @@ -#include <stdlib.h> -#include <string.h> - -#include "malloc.h" -#undef realloc - -void * -realloc(void *ptr, size_t nbytes) -{ - Header *oh, *prev, *next, *new; - size_t nunits, avail, onbytes, n; - - if (!nbytes) - return NULL; - - if (!ptr) - return malloc(nbytes); - - nunits = (nbytes + sizeof(Header) - 1) / sizeof(Header) + 1; - oh = (Header*)ptr - 1; - - if (oh->h.size == nunits) - return ptr; - - new = oh + nunits; - - if (nunits < oh->h.size - 1) { - new->h.size = oh->h.size - nunits; - oh->h.size = nunits; - free(new + 1); - return oh; - } - - prev = _prevchunk(oh); - - if (oh + oh->h.size == prev->h.next) { - /* - * if there is free space adjacent - * to the current memory - */ - next = prev->h.next; - avail = oh->h.size + next->h.size; - - if (avail == nunits) { - oh->h.size = nunits; - prev->h.next = next->h.next; - return oh; - } - - if (avail > nunits) { - oh->h.size = nunits; - prev->h.next = new; - new->h.next = next; - new->h.size = avail - nunits; - return oh; - } - } - - onbytes = (oh->h.size - 1) * sizeof(Header); - if ((new = malloc(nbytes)) == NULL) - return NULL; - - n = (onbytes > nbytes) ? nbytes : onbytes; - memcpy(new, ptr, n); - free(ptr); - - return new; -} diff --git a/lib/c/stdlib/strtoull.c b/lib/c/stdlib/strtoull.c @@ -1,64 +0,0 @@ -#include <ctype.h> -#include <errno.h> -#include <limits.h> -#include <stdlib.h> -#include <string.h> - -#undef strtoull - -unsigned long long -strtoull(const char *s, char **end, int base) -{ - int d, sign = 1; - unsigned long long n; - static const char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - const char *t, *p; - - while (isspace(*s)) - ++s; - - switch (*s) { - case '-': - sign = -1; - case '+': - ++s; - } - - if (base == 0) { - if (*s == '0' && toupper(s[1]) == 'X') - base = 16; - else if (*s == '0') - base = 8; - else - base = 10; - } - - if (base == 16 && *s == '0' && toupper(s[1]) == 'X') - s += 2; - - n = 0; - for (t = s; p = strchr(digits, toupper(*t)); ++t) { - if ((d = p - digits) >= base) - break; - if (n > ULLONG_MAX/base) - goto overflow; - n *= base; - if (d > ULLONG_MAX - n) - goto overflow; - n += d; - } - - - if (end) - *end = t; - if (n == 0 && s == t) - errno = EINVAL; - return n*sign; - -overflow: - if (end) - *end = t; - errno = ERANGE; - - return ULLONG_MAX; -} diff --git a/lib/c/string/Makefile b/lib/c/string/Makefile @@ -1,31 +0,0 @@ -.POSIX: -PROJECTDIR =../../.. -include $(PROJECTDIR)/scripts/rules.mk - -MORECFLAGS = -w - -OBJS = memchr.o\ - memcmp.o\ - memcpy.o\ - memmove.o\ - memset.o\ - strcat.o\ - strchr.o\ - strcmp.o\ - strcoll.o\ - strcpy.o\ - strcspn.o\ - strerror.o\ - strlen.o\ - strncat.o\ - strncmp.o\ - strncpy.o\ - strnlen.o\ - strpbrk.o\ - strrchr.o\ - strspn.o\ - strstr.o\ - strtok.o\ - strxfrm.o\ - -all: $(OBJS) diff --git a/lib/c/string/memchr.c b/lib/c/string/memchr.c @@ -1,12 +0,0 @@ -#include <string.h> -#undef memchr - -void * -memchr(const void *s, int c, size_t n) -{ - const unsigned char *bp = s; - - while (n > 0 && *bp++ != c) - --n; - return (n == 0) ? NULL : bp-1; -} diff --git a/lib/c/string/memcmp.c b/lib/c/string/memcmp.c @@ -1,14 +0,0 @@ -#include <string.h> -#undef memcmp - -int -memcmp(const void *s1, const void *s2, size_t n) -{ - const char *s = s1; - const char *t = s2; - - for ( ; n > 0 && *s == *t; --n) - ++s, ++t; - - return (n > 0) ? *(unsigned char *) s - *(unsigned char *) t : 0; -} diff --git a/lib/c/string/memcpy.c b/lib/c/string/memcpy.c @@ -1,13 +0,0 @@ -#include <string.h> -#undef memcpy - -void * -memcpy(void * restrict dst, const void * restrict src, size_t n) -{ - char *s1 = dst; - const char *s2 = src; - - while (n-- > 0) - *s1++ = *s2++; - return dst; -} diff --git a/lib/c/string/memmove.c b/lib/c/string/memmove.c @@ -1,18 +0,0 @@ -#include <string.h> -#undef memmove - -void * -memmove(void *dst, const void *src, size_t n) -{ - char *d = dst, *s = (char *) src; - - if (d < s) { - while (n-- > 0) - *d++ = *s++; - } else { - s += n-1, d += n-1; - while (n-- > 0) - *d-- = *s--; - } - return dst; -} diff --git a/lib/c/string/memset.c b/lib/c/string/memset.c @@ -1,12 +0,0 @@ -#include <string.h> -#undef memset - -void * -memset(void *s, int c, size_t n) -{ - char *m = s; - - while (n-- > 0) - *m++ = c; - return s; -} diff --git a/lib/c/string/strcat.c b/lib/c/string/strcat.c @@ -1,14 +0,0 @@ -#include <string.h> -#undef strcat - -char * -strcat(char * restrict dst, const char * restrict src) -{ - char *ret = dst; - - while (*dst) - ++dst; - while (*dst++ = *src++) - ; - return ret; -} diff --git a/lib/c/string/strchr.c b/lib/c/string/strchr.c @@ -1,10 +0,0 @@ -#include <string.h> -#undef strchr - -char * -strchr(const char *s, int c) -{ - while (*s && *s != c) - ++s; - return (*s == c) ? (char *)s : NULL; -} diff --git a/lib/c/string/strcmp.c b/lib/c/string/strcmp.c @@ -1,10 +0,0 @@ -#include <string.h> -#undef strcmp - -int -strcmp(const char *s1, const char *s2) -{ - while (*s1 && *s2 && *s1 == *s2) - ++s1, ++s2; - return *(unsigned char *)s1 - *(unsigned char *)s2; -} diff --git a/lib/c/string/strcoll.c b/lib/c/string/strcoll.c @@ -1,10 +0,0 @@ -#include <string.h> -#undef strcoll - -int -strcoll(const char *s1, const char *s2) -{ - while (*s1 && *s2 && *s1 == *s2) - ++s1, ++s2; - return *(unsigned char *) s1 - *(unsigned char *) s2; -} diff --git a/lib/c/string/strcpy.c b/lib/c/string/strcpy.c @@ -1,12 +0,0 @@ -#include <string.h> -#undef strcpy - -char * -strcpy(char * restrict dst, const char * restrict src) -{ - char *ret = dst; - - while (*dst++ = *src++) - ; - return ret; -} diff --git a/lib/c/string/strcspn.c b/lib/c/string/strcspn.c @@ -1,21 +0,0 @@ -#include <string.h> -#undef strcspn - -size_t -strcspn(const char *s1, const char *s2) -{ - const unsigned char *s = s1; - const unsigned char *accept = s2; - unsigned ch; - size_t n; - char buf[__NUMCHARS]; - - memset(buf, 0, sizeof(buf)); - while (ch = *accept++) - buf[ch] = 1; - - for (n = 0; (ch = *s++) && !buf[ch]; ++n) - ; - - return n; -} diff --git a/lib/c/string/strerror.c b/lib/c/string/strerror.c @@ -1,11 +0,0 @@ -#include <errno.h> -#include <string.h> -#undef strerror - -char * -strerror(int errnum) -{ - if (errnum > _sys_nerr) - errnum = EUNKNOWN; - return _sys_errlist[errnum]; -} diff --git a/lib/c/string/strlen.c b/lib/c/string/strlen.c @@ -1,12 +0,0 @@ -#include <string.h> -#undef strlen - -size_t -strlen(const char *s) -{ - const char *t; - - for (t = s; *t; ++t) - ; - return t - s; -} diff --git a/lib/c/string/strncat.c b/lib/c/string/strncat.c @@ -1,15 +0,0 @@ -#include <string.h> -#undef strncat - -char * -strncat(char * restrict dst, const char * restrict src, size_t n) -{ - char *ret = dst; - - while (*dst) - ++dst; - while (n-- > 0 && *src) - *dst++ = *src++; - *dst = '\0'; - return ret; -} diff --git a/lib/c/string/strncmp.c b/lib/c/string/strncmp.c @@ -1,14 +0,0 @@ -#include <string.h> -#undef strncmp - -int -strncmp(const char *s1, const char *s2, size_t n) -{ - int c; - - for ( ; n > 0 && (c = *s1) && c == *s2; --n) - ++s1, ++s2; - if (n == 0) - return 0; - return *(unsigned char *) s1 - *(unsigned char *) s2; -} diff --git a/lib/c/string/strncpy.c b/lib/c/string/strncpy.c @@ -1,14 +0,0 @@ -#include <string.h> -#undef strncpy - -char * -strncpy(char * restrict dst, const char * restrict src, size_t n) -{ - char *ret = dst; - - for (; n > 0 && *src; --n) - *dst++ = *src++; - while (n-- > 0) - *dst++ = '\0'; - return ret; -} diff --git a/lib/c/string/strnlen.c b/lib/c/string/strnlen.c @@ -1,13 +0,0 @@ -#include <string.h> - -#undef strnlen - -size_t -strnlen(const char *s, size_t maxlen) -{ - size_t n; - - for (n = 0; n < maxlen && *s++; ++n) - ; - return n; -} diff --git a/lib/c/string/strpbrk.c b/lib/c/string/strpbrk.c @@ -1,20 +0,0 @@ -#include <string.h> -#undef strpbrk - -char * -strpbrk(const char *s1, const char *s2) -{ - const unsigned char *s = s1; - const unsigned char *accept = s2; - unsigned ch; - char buf[__NUMCHARS]; - - memset(buf, 0, sizeof(buf)); - while (ch = *accept++) - buf[ch] = 1; - - while ((ch = *s) && !buf[ch]) - s++; - - return (ch == '\0') ? NULL : (char *) s; -} diff --git a/lib/c/string/strrchr.c b/lib/c/string/strrchr.c @@ -1,14 +0,0 @@ -#include <string.h> -#undef strrchr - -char * -strrchr(const char *s, int c) -{ - const char *t = s; - - while (*t) - ++t; - while (t > s && *t != c) - --t; - return (*t == c) ? (char *)t : NULL; -} diff --git a/lib/c/string/strspn.c b/lib/c/string/strspn.c @@ -1,21 +0,0 @@ -#include <string.h> -#undef strspn - -size_t -strspn(const char *s1, const char *s2) -{ - const unsigned char *s = s1; - const unsigned char *accept = s2; - unsigned ch; - size_t n; - char buf[__NUMCHARS]; - - memset(buf, 0, sizeof(buf)); - while (ch = *accept++) - buf[ch] = 1; - - for (n = 0; (ch = *s++) && buf[ch]; ++n) - ; - - return n; -} diff --git a/lib/c/string/strstr.c b/lib/c/string/strstr.c @@ -1,18 +0,0 @@ -#include <stddef.h> -#include <string.h> -#undef strstr - -char * -strstr(const char *s1, const char *s2) -{ - const char *p; - int c = *s2; - - if (c == '\0') - return NULL; - for (p = s1; p = strchr(p, c); ++p) { - if (!strcmp(p, s2)) - return (char *) p; - } - return NULL; -} diff --git a/lib/c/string/strtok.c b/lib/c/string/strtok.c @@ -1,25 +0,0 @@ -#include <string.h> -#undef strtok - -char * -strtok(char * restrict s, const char * restrict delim) -{ - static char *line; - - if (s) - line = s; - if (!s && !line) - return NULL; - - s = line + strspn(line, delim); - if (*s == '\0') - return line = NULL; - - line = s + strcspn(s, delim); - if (*line != '\0') - *line++ = '\0'; - else - line = NULL; - - return s; -} diff --git a/lib/c/string/strxfrm.c b/lib/c/string/strxfrm.c @@ -1,12 +0,0 @@ -#include <string.h> -#undef strxfrm - -size_t -strxfrm(char * restrict dst, const char * restrict src, size_t n) -{ - size_t len = strlen(src); - - if (len < n) - strcpy(dst, src); - return len; -} diff --git a/lib/c/syscall.h b/lib/c/syscall.h @@ -1,8 +0,0 @@ -extern void *_brk(void *addr); -extern int _open(const char *path, int flags); -extern int _close(int fd); -extern int _read(int fd, void *buf, size_t n); -extern int _write(int fd, void *buf, size_t n); -extern int _lseek(int fd, long off, int whence); -extern void _Exit(int status); -extern int _access(char *path, int mode); diff --git a/lib/c/time/Makefile b/lib/c/time/Makefile @@ -1,16 +0,0 @@ -.POSIX: -PROJECTDIR =../../.. -include $(PROJECTDIR)/scripts/rules.mk - -MORECFLAGS = -w - -OBJS = _daysyear.o\ - asctime.o\ - ctime.o\ - difftime.o\ - gmtime.o\ - localtime.o\ - mktime.o\ - strftime.o\ - -all: $(OBJS) diff --git a/lib/c/time/_daysyear.c b/lib/c/time/_daysyear.c @@ -1,30 +0,0 @@ -#include <time.h> -#include "../libc.h" - -int _daysmon[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; - -int -_daysyear(int year) -{ - if (year%4 != 0) - return 365; - if (year%100 == 0 && year%400 != 0) - return 365; - return 366; -} - -/* - * Happy New Year!!!! - */ -int -_newyear(int year) -{ - int day; - - year += 1900 - 1; - day = 1 + year + year/4; - day -= year/100; - day += year/400; - - return day % 7; -} diff --git a/lib/c/time/asctime.c b/lib/c/time/asctime.c @@ -1,12 +0,0 @@ -#include <time.h> -#undef asctime - -#include <stdio.h> // TODO: remove me! -char * -asctime(const struct tm *tm) -{ - static char buf[30]; - - strftime(buf, sizeof(buf), "%c\n", tm); - return buf; -} diff --git a/lib/c/time/ctime.c b/lib/c/time/ctime.c @@ -1,8 +0,0 @@ -#include <time.h> -#undef ctime - -char * -ctime(const time_t *t) -{ - return asctime(localtime(t)); -} diff --git a/lib/c/time/difftime.c b/lib/c/time/difftime.c @@ -1,8 +0,0 @@ -#include <time.h> -#undef difftime - -double -difftime(time_t t1, time_t t2) -{ - return (double) (t1 - t2); -} diff --git a/lib/c/time/gmtime.c b/lib/c/time/gmtime.c @@ -1,35 +0,0 @@ -#include <time.h> -#include "libc.h" -#undef gmtime - -struct tm * -gmtime(const time_t *t) -{ - static struct tm tm; - time_t sec, min, hour, year, day; - int i; - - tm.tm_sec = *t % SECDAY; - tm.tm_min = tm.tm_sec / 60; - tm.tm_sec %= 60; - tm.tm_hour = tm.tm_min / 60; - tm.tm_min %= 60; - day = *t / SECDAY; - - tm.tm_wday = (day + THU) % 7; /* 1/1/1970 was Thursday */ - - for (i = EPOCH; day >= _daysyear(i); ++i) - day -= _daysyear(i); - tm.tm_year = i - 1900; - tm.tm_yday = day; - - _daysmon[FEB] = FEBDAYS(tm.tm_year); - for (i = JAN; day > _daysmon[i]; i++) - day -= _daysmon[i]; - tm.tm_mon = i; - tm.tm_mday = day + 1; - - tm.tm_isdst = 0; - - return &tm; -} diff --git a/lib/c/time/localtime.c b/lib/c/time/localtime.c @@ -1,21 +0,0 @@ -#include <time.h> -#include "libc.h" -#undef localtime - -struct tm * -localtime(const time_t *timep) -{ - struct tzone *tz; - struct tm *tm; - time_t t = *timep; - - t += tz->gmtoff * 60; - t += tz->isdst * 60; - tm = gmtime(&t); - tz = _tzone(tm); - tm->tm_zone = tz->name; - tm->tm_isdst = tz->isdst; - tm->tm_gmtoff = tz->gmtoff; - - return tm; -} diff --git a/lib/c/time/mktime.c b/lib/c/time/mktime.c @@ -1,112 +0,0 @@ -#include <limits.h> -#include <time.h> -#include "libc.h" -#undef mktime - -static int -norm(int *val, int *next, int qty) -{ - int v = *val, n = *next, d; - - if (v < 0) { - d = -v / qty + 1; - v += d * qty; - if (n > INT_MAX - d) - return 0; - n += d; - } - if (v >= qty) { - d = v / qty; - v -= d * qty; - if (n < INT_MIN + d) - return 0; - n -= d; - } - - *val = v; - *next = n; - return 1; -} - -static int -normalize(struct tm *tm) -{ - int mon, day, year; - struct tm aux = *tm; - - if (!norm(&tm->tm_sec, &tm->tm_min, 60) || - !norm(&tm->tm_min, &tm->tm_hour, 60) || - !norm(&tm->tm_hour, &tm->tm_mday, 24) || - !norm(&tm->tm_mon, &tm->tm_year, 12)) { - return 0; - } - - day = tm->tm_mday; - year = EPOCH + tm->tm_year; - _daysmon[FEB] = FEBDAYS(year); - - for (mon = tm->tm_mon; day < 1; --mon) { - day += _daysmon[mon]; - if (mon == JAN) { - if (year == EPOCH) - return -1; - year--; - _daysmon[FEB] = FEBDAYS(year); - mon = DEC+1; - } - } - - for (; day > _daysmon[mon]; ++mon) { - day -= _daysmon[mon]; - if (mon == DEC) { - if (year == _MAXYEAR) - return -1; - year++; - _daysmon[FEB] = FEBDAYS(year); - mon = JAN-1; - } - } - - tm->tm_mon = mon; - tm->tm_year = year - EPOCH; - tm->tm_mday = day; - tm->tm_wday = (_newyear(tm->tm_year) + tm->tm_yday) % 7; - - return 1; -} - -time_t -mktime(struct tm *tm) -{ - int i, year, dst; - time_t t; - struct tm *aux; - - if (!normalize(tm)) - return -1; - - t = 0; - year = tm->tm_year + 1900; - for (i = EPOCH; i < year; i++) - t += _daysyear(i) * SECDAY; - - for (i = 0; i < tm->tm_mon; i++) - t += _daysmon[i] * SECDAY; - - t += tm->tm_sec; - t += tm->tm_min * SECMIN; - t += tm->tm_hour * SECHOUR; - t += (tm->tm_mday-1) * SECDAY; - - aux = localtime(&t); - - dst = 0; - if (tm->tm_isdst == 0 && aux->tm_isdst == 1) - dst = -SECHOUR; - else if (tm->tm_isdst == 1 && aux->tm_isdst == 0) - dst = +SECHOUR; - - t += aux->tm_gmtoff + dst; - - return t; -} diff --git a/lib/c/time/strftime.c b/lib/c/time/strftime.c @@ -1,246 +0,0 @@ -#include <time.h> -#include <string.h> -#include "libc.h" -#undef strftime - -static char *days[] = { - "Sunday", "Monday", "Tuesday", "Wednesday", - "Thursday", "Friday", "Saturday", -}; - -static char *months[] = { - "January", "February", "March", "April", - "May", "June", "July", "August", - "September", "October", "November", "December" -}; - -static char *am_pm[] = {"AM", "PM"}; - -static size_t -sval(char *s, size_t siz, char **strs, int abrev, int idx, int max) -{ - char *str; - size_t len; - - if (idx < 0 && idx >= max) - goto wrong; - - str = strs[idx]; - len = (!abrev) ? strlen(str) : 3; - if (len > siz) - goto wrong; - - memcpy(s, str, len); - return len; - -wrong: - *s = '?'; - return 1; -} - -static size_t -dval(char *s, size_t siz, int prec, int fill, int val) -{ - char *t; - int n; - static char digits[] = "0123456789"; - - if (prec > siz || val < 0) { - *s = '?'; - return 1; - } - - n = prec; - do { - s[--n] = digits[val % 10]; - val /= 10; - } while (n > 0 && val > 0); - - while (n > 0) - s[--n] = fill; - - return prec; -} - -static size_t -timezone(char *s, size_t prec, const struct tm * restrict tm) -{ - long off = tm->tm_gmtoff; - - if (prec < 5) { - *s = '?'; - return 1; - } - - if (off >= 0) { - *s++ = '+'; - } else { - *s++ = '-'; - off = -off; - } - - dval(s, 2, 2, '0', off / 3600); - dval(s, 2, 2, '0', (off % 3600) / 60); - - return 5; -} - -size_t -strftime(char * restrict s, size_t siz, - const char * restrict fmt, - const struct tm * restrict tm) -{ - int ch, abrev, val, fill, width; - size_t n, inc; - char *tfmt; - - for (n = siz-1; (ch = *fmt++) && n > 0; s += inc, n -= inc) { - if (ch != '%') { - *s = ch; - inc = 1; - continue; - } - - abrev = 0; - fill = '0'; - width = 2; - - switch (*fmt++) { - case 'Z': - if (!tm->tm_zone) - break; - inc = sval(s, n, &tm->tm_zone, 0, 0, 1); - break; - case 'a': - abrev = 1; - case 'A': - inc = sval(s, n, days, abrev, tm->tm_wday, 7); - break; - case 'h': - case 'b': - abrev = 1; - case 'B': - inc = sval(s, n, months, abrev, tm->tm_mon, 12); - break; - case 'p': - inc = sval(s, n, am_pm, 0, tm->tm_hour > 12, 2); - break; - case 'c': - tfmt = "%a %b %e %T %Y"; - goto recursive; - case 'D': - tfmt = "%m/%d/%y"; - goto recursive; - case 'F': - tfmt = "%Y-%m-%d"; - goto recursive; - case 'R': - tfmt = "%H:%M"; - goto recursive; - case 'X': - case 'T': - tfmt = "%H:%M:%S"; - goto recursive; - case 'r': - tfmt = "%I:%M:%S %p"; - goto recursive; - case 'x': - tfmt = "%m/%d/%y"; - goto recursive; - recursive: - inc = strftime(s, n+1, tfmt, tm) - 1; - break; - case 'n': - val = '\n'; - goto character; - case 't': - val = '\t'; - goto character; - case '%': - val = '%'; - character: - *s = val; - inc = 1; - break; - case 'e': - fill = ' '; - val = tm->tm_mday; - goto number; - case 'd': - val = tm->tm_mday; - goto number; - case 'V': - case 'g': - case 'G': - /* TODO */ - break; - case 'C': - val = tm->tm_year / 100; - goto number; - case 'H': - val = tm->tm_hour; - goto number; - case 'I': - val = tm->tm_hour; - if (val == 0) - val = 12; - if (val > 12) - val -= 12; - goto number; - case 'j': - width = 3; - val = tm->tm_yday+1; - goto number; - case 'm': - val = tm->tm_mon+1; - goto number; - case 'M': - val = tm->tm_min; - goto number; - case 'S': - val = tm->tm_sec; - goto number; - case 'u': - width = 1; - val = tm->tm_wday+1; - goto number; - case 'U': - val = tm->tm_yday / 7; - if (_newyear(tm->tm_year) == SAT) - val++; - goto number; - case 'W': - val = tm->tm_yday / 7; - if (_newyear(tm->tm_year) == MON) - val++; - goto number; - case 'w': - width = 1; - val = tm->tm_wday; - goto number; - case 'y': - val = tm->tm_year%100; - goto number; - case 'Y': - width = 4; - val = 1900 + tm->tm_year; - number: - inc = dval(s, n, width, fill, val); - break; - case 'z': - inc = timezone(s, n, tm); - break; - case 'E': - case 'O': - if (*fmt != '\0') - fmt += 2;; - case '\0': - inc = 0; - --fmt; - break; - } - } - *s = '\0'; - - return siz - n; -} diff --git a/lib/coff32/Makefile b/lib/coff32/Makefile @@ -1,22 +0,0 @@ -.POSIX: - -PROJECTDIR = ../.. -LIBCOFF32 = . -include $(PROJECTDIR)/rules.mk -include objlst.mk - -TARGET = $(LIBDIR)/libcoff32.a - -all: $(TARGET) - -$(TARGET): $(LIBCOFF32-OBJ) - $(AR) $(ARFLAGS) $@ $? - ranlib $@ - -dep: - $(PROJECTDIR)/mkdep.sh - -clean: - rm -f *.o $(TARGET) - -include deps.mk diff --git a/lib/coff32/coff32_pack_aout.c b/lib/coff32/coff32_pack_aout.c @@ -1,9 +0,0 @@ -#include <assert.h> - -#include "../../inc/coff32/aouthdr.h" -#include "../../inc/coff32/coff32.h" - -void -coff32_pack_aout(packfun fun, unsigned char *buff, AOUTHDR *aout) -{ -} diff --git a/lib/coff32/coff32_pack_ent.c b/lib/coff32/coff32_pack_ent.c @@ -1,20 +0,0 @@ -#include <assert.h> - -#include "../../inc/coff32/syms.h" -#include "../../inc/coff32/coff32.h" - -void -coff32_pack_ent(packfun fun, unsigned char *buff, SYMENT *ent) -{ - int n; - - n = (*fun)(buff, - "'8lsscc", - &ent->n_name, - &ent->n_value, - &ent->n_scnum, - &ent->n_type, - &ent->n_sclass, - &ent->n_numaux); - assert(n == SYMESZ); -} diff --git a/lib/coff32/coff32_pack_hdr.c b/lib/coff32/coff32_pack_hdr.c @@ -1,21 +0,0 @@ -#include <assert.h> - -#include "../../inc/coff32/filehdr.h" -#include "../../inc/coff32/coff32.h" - -void -coff32_pack_hdr(packfun fun, unsigned char *buff, FILHDR *hdr) -{ - int n; - - n = (*fun)(buff, - "sslllss", - hdr->f_magic, - hdr->f_nscns, - hdr->f_timdat, - hdr->f_symptr, - hdr->f_nsyms, - hdr->f_opthdr, - hdr->f_flags); - assert(n == FILHSZ); -} diff --git a/lib/coff32/coff32_pack_scn.c b/lib/coff32/coff32_pack_scn.c @@ -1,24 +0,0 @@ -#include <assert.h> - -#include "../../inc/coff32/scnhdr.h" -#include "../../inc/coff32/coff32.h" - -void -coff32_pack_scn(packfun fun, unsigned char *buff, SCNHDR *scn) -{ - int n; - - n = (*fun)(buff, - "'8llllllssl", - scn->s_name, - scn->s_paddr, - scn->s_vaddr, - scn->s_size, - scn->s_scnptr, - scn->s_relptr, - scn->s_lnnoptr, - scn->s_nrelloc, - scn->s_nlnno, - scn->s_flags); - assert(n == SCNHSZ); -} diff --git a/lib/coff32/coff32_unpack_aout.c b/lib/coff32/coff32_unpack_aout.c @@ -1,9 +0,0 @@ -#include <assert.h> - -#include "../../inc/coff32/aouthdr.h" -#include "../../inc/coff32/coff32.h" - -void -coff32_unpack_aout(packfun fun, unsigned char *buff, AOUTHDR *ent) -{ -} diff --git a/lib/coff32/coff32_unpack_ent.c b/lib/coff32/coff32_unpack_ent.c @@ -1,20 +0,0 @@ -#include <assert.h> - -#include "../../inc/coff32/syms.h" -#include "../../inc/coff32/coff32.h" - -void -coff32_unpack_ent(packfun fun, unsigned char *buff, SYMENT *ent) -{ - int n; - - n = (*fun)(buff, - "'8lsscc", - &ent->n_name, - &ent->n_value, - &ent->n_scnum, - &ent->n_type, - &ent->n_sclass, - &ent->n_numaux); - assert(n == SYMESZ); -} diff --git a/lib/coff32/coff32_unpack_hdr.c b/lib/coff32/coff32_unpack_hdr.c @@ -1,22 +0,0 @@ -#include <assert.h> - -#include "../../inc/coff32/filehdr.h" -#include "../../inc/coff32/coff32.h" - -void -coff32_unpack_hdr(packfun fun, unsigned char *buff, FILHDR *hdr) -{ - int n; - - n = (*fun)(buff, - "sslllss", - &hdr->f_magic, - &hdr->f_nscns, - &hdr->f_timdat, - &hdr->f_symptr, - &hdr->f_nsyms, - &hdr->f_opthdr, - &hdr->f_flags); - assert(n == FILHSZ); -} - diff --git a/lib/coff32/coff32_unpack_scn.c b/lib/coff32/coff32_unpack_scn.c @@ -1,24 +0,0 @@ -#include <assert.h> - -#include "../../inc/coff32/scnhdr.h" -#include "../../inc/coff32/coff32.h" - -void -coff32_unpack_scn(packfun fun, unsigned char *buff, SCNHDR *scn) -{ - int n; - - n = (*fun)(buff, - "'8llllllssl", - scn->s_name, - &scn->s_paddr, - &scn->s_vaddr, - &scn->s_size, - &scn->s_scnptr, - &scn->s_relptr, - &scn->s_lnnoptr, - &scn->s_nrelloc, - &scn->s_nlnno, - &scn->s_flags); - assert(n == SCNHSZ); -} diff --git a/lib/coff32/deps.mk b/lib/coff32/deps.mk @@ -1,17 +0,0 @@ -#deps -coff32_pack_aout.o: ../../inc/coff32/aouthdr.h -coff32_pack_aout.o: ../../inc/coff32/coff32.h -coff32_pack_ent.o: ../../inc/coff32/coff32.h -coff32_pack_ent.o: ../../inc/coff32/syms.h -coff32_pack_hdr.o: ../../inc/coff32/coff32.h -coff32_pack_hdr.o: ../../inc/coff32/filehdr.h -coff32_pack_scn.o: ../../inc/coff32/coff32.h -coff32_pack_scn.o: ../../inc/coff32/scnhdr.h -coff32_unpack_aout.o: ../../inc/coff32/aouthdr.h -coff32_unpack_aout.o: ../../inc/coff32/coff32.h -coff32_unpack_ent.o: ../../inc/coff32/coff32.h -coff32_unpack_ent.o: ../../inc/coff32/syms.h -coff32_unpack_hdr.o: ../../inc/coff32/coff32.h -coff32_unpack_hdr.o: ../../inc/coff32/filehdr.h -coff32_unpack_scn.o: ../../inc/coff32/coff32.h -coff32_unpack_scn.o: ../../inc/coff32/scnhdr.h diff --git a/lib/coff32/libdep.mk b/lib/coff32/libdep.mk @@ -1,4 +0,0 @@ -include $(LIBCOFF32)/objlst.mk - -$(LIBDIR)/libcoff32.a: $(LIBCOFF32-OBJ) - +cd $(LIBCOFF32) && $(MAKE) diff --git a/lib/coff32/objlst.mk b/lib/coff32/objlst.mk @@ -1,9 +0,0 @@ - -LIBCOFF32-OBJ = $(LIBCOFF32)/coff32_pack_hdr.o \ - $(LIBCOFF32)/coff32_unpack_hdr.o \ - $(LIBCOFF32)/coff32_pack_scn.o \ - $(LIBCOFF32)/coff32_unpack_scn.o \ - $(LIBCOFF32)/coff32_pack_aout.o \ - $(LIBCOFF32)/coff32_unpack_aout.o \ - $(LIBCOFF32)/coff32_pack_ent.o \ - $(LIBCOFF32)/coff32_unpack_ent.o diff --git a/lib/crt/Makefile b/lib/crt/Makefile @@ -1,14 +0,0 @@ -.POSIX: - -PROJECTDIR = ../.. -include $(PROJECTDIR)/rules.mk - -DIRS = amd64-sysv-linux amd64-sysv-openbsd amd64-sysv-netbsd - -all: $(DIRS) - -$(DIRS): FORCE - @cd $@ && $(MAKE) - -clean: - $(FORALL) diff --git a/lib/crt/amd64-sysv-linux/Makefile b/lib/crt/amd64-sysv-linux/Makefile @@ -1,9 +0,0 @@ -.POSIX: - -PROJECTDIR = ../../.. -include $(PROJECTDIR)/rules.mk - -CRT = $(LIBDIR)/amd64-sysv-linux/crt.o -TARGETS = $(CRT) - -include ../common.mk diff --git a/lib/crt/amd64-sysv-linux/crt.s b/lib/crt/amd64-sysv-linux/crt.s @@ -1,8 +0,0 @@ - .file "crt.s" - - .text - .global _start -_start: - call main - movl %eax, %edi - jmp exit diff --git a/lib/crt/amd64-sysv-netbsd/Makefile b/lib/crt/amd64-sysv-netbsd/Makefile @@ -1,9 +0,0 @@ -.POSIX: - -PROJECTDIR = ../../.. -include $(PROJECTDIR)/rules.mk - -CRT = $(LIBDIR)/amd64-sysv-netbsd/crt.o -TARGETS = $(CRT) - -include ../common.mk diff --git a/lib/crt/amd64-sysv-netbsd/crt.s b/lib/crt/amd64-sysv-netbsd/crt.s @@ -1,30 +0,0 @@ - .file "crt.s" - - .section .note.netbsd.ident - .long 7 - .long 4 - .long 1 - .ascii "NetBSD\0" - .p2align 2 - .long 200000000 - - .bss - .globl _environ -_environ: - .quad 0 - - .text - .align 8 - .global _start -_start: - andq $-16,%rsp - movq %rsp,%rbp - - movq (%rbp),%rdi # rdi = argc - leaq 8(%rbp),%rsi # rsi = argv - leaq 16(%rbp,%rdi,8),%rdx # rdx = envp = argv +8*argc + 8 - movq %rdx,_environ - - call main - movl %eax,%edi - jmp exit diff --git a/lib/crt/amd64-sysv-openbsd/Makefile b/lib/crt/amd64-sysv-openbsd/Makefile @@ -1,9 +0,0 @@ -.POSIX: - -PROJECTDIR = ../../.. -include $(PROJECTDIR)/rules.mk - -CRT = $(LIBDIR)/amd64-sysv-openbsd/crt.o -TARGETS = $(CRT) - -include ../common.mk diff --git a/lib/crt/amd64-sysv-openbsd/crt.s b/lib/crt/amd64-sysv-openbsd/crt.s @@ -1,18 +0,0 @@ - .file "crt.s" - - .section ".note.openbsd.ident", "a" - .p2align 2 - .long 8 - .long 4 - .long 1 - .ascii "OpenBSD\0" - .long 0 - .p2align 2 - - .text - .align 8 - .global _start -_start: - call main - movl %eax, %edi - jmp exit diff --git a/lib/crt/common.mk b/lib/crt/common.mk @@ -1,8 +0,0 @@ -all: $(TARGETS) - -$(CRT): crt.o - cp crt.o $@ - -clean: - rm -f *.o - rm -f $(TARGETS) diff --git a/lib/crt/i386-sysv-linux/crt.s b/lib/crt/i386-sysv-linux/crt.s @@ -1 +0,0 @@ -/* TODO */ diff --git a/lib/crt/i386-sysv-openbsd/crt.s b/lib/crt/i386-sysv-openbsd/crt.s @@ -1 +0,0 @@ -/* TODO */ diff --git a/lib/crt/z80-scc-none/crt.s b/lib/crt/z80-scc-none/crt.s @@ -1,8 +0,0 @@ - .file "crt.s" - - .text - .global _start -_start: - call main -# ex %de,%hl - call exit diff --git a/lib/scc/Makefile b/lib/scc/Makefile @@ -1,21 +0,0 @@ - -PROJECTDIR = ../.. -LIBSCC = . -include $(PROJECTDIR)/rules.mk -include objlst.mk - -TARGET = $(LIBDIR)/libscc.a - -all: $(TARGET) - -$(TARGET): $(LIBSCC-OBJ) - $(AR) $(ARFLAGS) $@ $? - ranlib $@ - -dep: - $(PROJECTDIR)/mkdep.sh - -clean: - rm -f *.o $(LIBDIR)/libscc.a - -include deps.mk diff --git a/lib/scc/alloc.c b/lib/scc/alloc.c @@ -1,112 +0,0 @@ -static char sccsid[] = "@(#) ./lib/scc/alloc.c"; -#include <stdlib.h> -#include "../../inc/scc.h" - -/* - * This is the most pedantic piece of code that I have written - * in my life. The next union is used to enforce the aligmnet - * of the address returned by new(). A union has the aligment - * of the field with the biggest aligment. This union has all - * the types that we use in scc, and we round all the address - * to the aligment of this struct, so we can be sure that any - * pointer using that address will be safe. The field ap is - * in the union to be sure that struct pointers are included - * in the list, although they will have the same aligment or - * smaller than void *, but I wanted to be pedantic. - */ -union hdr { - union hdr *next; - struct arena *ap; - char c; - unsigned char uc; - int i; - short s; - long l; - long long ll; - float f; - double d; - long double ld; - void *vp; -}; - -struct arena { - struct arena *next; - union hdr *array; -}; - -struct alloc { - size_t size; - size_t nmemb; - size_t padding; - struct arena *arena; - union hdr *freep; -}; - -static void -newarena(Alloc *allocp) -{ - struct arena *ap; - union hdr *bp, *lim; - size_t unit, n = allocp->nmemb; - - unit = (allocp->size-1) / sizeof(union hdr) + 1; - ap = xmalloc(sizeof(struct arena)); - ap->array = xmalloc(unit * sizeof(union hdr) * n); - - bp = ap->array; - for (lim = &bp[unit * (n-1)]; bp < lim; bp += unit) - bp->next = bp + unit; - bp->next = NULL; - - ap->next = allocp->arena; - allocp->arena = ap; - allocp->freep = ap->array; -} - -Alloc * -alloc(size_t size, size_t nmemb) -{ - Alloc *allocp = xmalloc(sizeof(*allocp)); - - allocp->size = size; - allocp->nmemb = nmemb; - allocp->arena = NULL; - allocp->freep = NULL; - - return allocp; -} - -void -dealloc(Alloc *allocp) -{ - struct arena *ap, *next; - - for (ap = allocp->arena; ap; ap = next) { - next = ap->next; - free(ap->array); - free(ap); - } - free(allocp); -} - -void * -new(Alloc *allocp) -{ - union hdr *bp; - - if (!allocp->freep) - newarena(allocp); - bp = allocp->freep; - allocp->freep = bp->next; - - return bp; -} - -void -delete(Alloc *allocp, void *p) -{ - union hdr *bp = p; - - bp->next = allocp->freep; - allocp->freep = bp; -} diff --git a/lib/scc/bpack.c b/lib/scc/bpack.c @@ -1,64 +0,0 @@ -#include <ctype.h> -#include <stdarg.h> - -#include "../../inc/scc.h" - -int -bpack(unsigned char *dst, char *fmt, ...) -{ - unsigned char *bp, *cp; - unsigned s; - unsigned long l; - unsigned long long q; - size_t n; - int d; - va_list va; - - bp = dst; - va_start(va, fmt); - while (*fmt) { - switch (*fmt++) { - case '\'': - for (n = 0; isdigit(*fmt); n += d) { - n *= 10; - d = *fmt++ - '0'; - } - cp = va_arg(va, unsigned char *); - while (n--) - *bp++ = *cp++; - break; - case 'c': - *bp++ = va_arg(va, unsigned); - break; - case 's': - s = va_arg(va, unsigned); - *bp++ = s >> 8; - *bp++ = s; - break; - case 'l': - l = va_arg(va, unsigned long); - *bp++ = l >> 24; - *bp++ = l >> 16; - *bp++ = l >> 8; - *bp++ = l; - break; - case 'q': - q = va_arg(va, unsigned long long); - *bp++ = q >> 56; - *bp++ = q >> 48; - *bp++ = q >> 40; - *bp++ = q >> 32; - *bp++ = q >> 24; - *bp++ = q >> 16; - *bp++ = q >> 8; - *bp++ = q; - break; - default: - va_end(va); - return -1; - } - } - va_end(va); - - return bp - dst; -} diff --git a/lib/scc/bunpack.c b/lib/scc/bunpack.c @@ -1,71 +0,0 @@ -static char sccsid[] = "@(#) ./lib/scc/lunpack.c"; - -#include <ctype.h> -#include <stdarg.h> - -#include "../../inc/scc.h" - -int -lunpack(unsigned char *src, char *fmt, ...) -{ - unsigned char *bp, *cp; - unsigned short *sp; - unsigned s; - unsigned long *lp, l; - unsigned long long *qp, q; - va_list va; - size_t n; - int d; - - bp = src; - va_start(va, fmt); - while (*fmt) { - switch (*fmt++) { - case '\'': - for (n = 0; isdigit(*fmt); n += d) { - n *= 10; - d = *fmt++ - '0'; - } - cp = va_arg(va, unsigned char *); - while (n--) - *cp++ = *bp++; - break; - case 'c': - cp = va_arg(va, unsigned char *); - *cp = *bp++; - break; - case 's': - sp = va_arg(va, unsigned short *); - s = (unsigned) *bp++ << 8; - s |= (unsigned) *bp++; - *sp = s; - break; - case 'l': - lp = va_arg(va, unsigned long *); - l = (unsigned long) *bp++ << 24; - l |= (unsigned long) *bp++ << 16; - l |= (unsigned long) *bp++ << 8; - l |= (unsigned long) *bp++; - *lp = l; - break; - case 'q': - qp = va_arg(va, unsigned long long *); - q = (unsigned long long) *bp++ << 56; - q |= (unsigned long long) *bp++ << 48; - q |= (unsigned long long) *bp++ << 40; - q |= (unsigned long long) *bp++ << 32; - q |= (unsigned long long) *bp++ << 24; - q |= (unsigned long long) *bp++ << 16; - q |= (unsigned long long) *bp++ << 8; - q |= (unsigned long long) *bp++; - *qp = q; - break; - default: - va_end(va); - return -1; - } - } - va_end(va); - - return bp - src; -} diff --git a/lib/scc/casecmp.c b/lib/scc/casecmp.c @@ -1,11 +0,0 @@ -static char sccsid[] = "@(#) ./lib/scc/casecmp.c"; -#include <ctype.h> -#include "../../inc/scc.h" - -int -casecmp(const char *s1, const char *s2) -{ - while (*s1 && toupper(*s1) == toupper(*s2)) - ++s1, ++s2; - return *s1 - *s2; -} diff --git a/lib/scc/debug.c b/lib/scc/debug.c @@ -1,20 +0,0 @@ -static char sccsid[] = "@(#) ./lib/scc/debug.c"; -#include <stdarg.h> -#include <stdio.h> - -#include "../../inc/scc.h" - -int debug; - -void -dbg(const char *fmt, ...) -{ - if (!debug) - return; - va_list va; - va_start(va, fmt); - vfprintf(stderr, fmt, va); - putc('\n', stderr); - va_end(va); - return; -} diff --git a/lib/scc/deps.mk b/lib/scc/deps.mk @@ -1,18 +0,0 @@ -#deps -alloc.o: ../../inc/scc.h -bpack.o: ../../inc/scc.h -bunpack.o: ../../inc/scc.h -casecmp.o: ../../inc/scc.h -debug.o: ../../inc/scc.h -die.o: ../../inc/scc.h -lpack.o: ../../inc/scc.h -lunpack.o: ../../inc/scc.h -newitem.o: ../../inc/scc.h -rmyro.o: ../../inc/myro.h -rmyro.o: ../../inc/scc.h -wmyro.o: ../../inc/myro.h -wmyro.o: ../../inc/scc.h -xcalloc.o: ../../inc/scc.h -xmalloc.o: ../../inc/scc.h -xrealloc.o: ../../inc/scc.h -xstrdup.o: ../../inc/scc.h diff --git a/lib/scc/die.c b/lib/scc/die.c @@ -1,20 +0,0 @@ -static char sccsid[] = "@(#) ./lib/scc/die.c"; -#include <stdarg.h> -#include <stdlib.h> -#include <stdio.h> - -#include "../../inc/scc.h" - -int failure; - -void -die(const char *fmt, ...) -{ - failure = 1; - va_list va; - va_start(va, fmt); - vfprintf(stderr, fmt, va); - putc('\n', stderr); - va_end(va); - exit(1); -} diff --git a/lib/scc/libdep.mk b/lib/scc/libdep.mk @@ -1,4 +0,0 @@ -include $(LIBSCC)/objlst.mk - -$(LIBDIR)/libscc.a: $(LIBSCC-OBJ) - +@cd $(LIBSCC) && $(MAKE) diff --git a/lib/scc/lpack.c b/lib/scc/lpack.c @@ -1,64 +0,0 @@ -#include <ctype.h> -#include <stdarg.h> - -#include "../../inc/scc.h" - -int -lpack(unsigned char *dst, char *fmt, ...) -{ - unsigned char *bp, *cp; - unsigned s; - unsigned long l; - unsigned long long q; - size_t n; - int d; - va_list va; - - bp = dst; - va_start(va, fmt); - while (*fmt) { - switch (*fmt++) { - case '\'': - for (n = 0; isdigit(*fmt); n += d) { - n *= 10; - d = *fmt++ - '0'; - } - cp = va_arg(va, unsigned char *); - while (n--) - *bp++ = *cp++; - break; - case 'c': - *bp++ = va_arg(va, unsigned); - break; - case 's': - s = va_arg(va, unsigned); - *bp++ = s; - *bp++ = s >> 8; - break; - case 'l': - l = va_arg(va, unsigned long); - *bp++ = l; - *bp++ = l >> 8; - *bp++ = l >> 16; - *bp++ = l >> 24; - break; - case 'q': - q = va_arg(va, unsigned long long); - *bp++ = q; - *bp++ = q >> 8; - *bp++ = q >> 16; - *bp++ = q >> 24; - *bp++ = q >> 32; - *bp++ = q >> 40; - *bp++ = q >> 48; - *bp++ = q >> 56; - break; - default: - va_end(va); - return -1; - } - } - va_end(va); - - return bp - dst; -} diff --git a/lib/scc/lunpack.c b/lib/scc/lunpack.c @@ -1,71 +0,0 @@ -static char sccsid[] = "@(#) ./lib/scc/lunpack.c"; - -#include <ctype.h> -#include <stdarg.h> - -#include "../../inc/scc.h" - -int -lunpack(unsigned char *src, char *fmt, ...) -{ - unsigned char *bp, *cp; - unsigned short *sp; - unsigned s; - unsigned long *lp, l; - unsigned long long *qp, q; - va_list va; - size_t n; - int d; - - bp = src; - va_start(va, fmt); - while (*fmt) { - switch (*fmt++) { - case '\'': - for (n = 0; isdigit(*fmt); n += d) { - n *= 10; - d = *fmt++ - '0'; - } - cp = va_arg(va, unsigned char *); - while (n--) - *cp++ = *bp++; - break; - case 'c': - cp = va_arg(va, unsigned char *); - *cp = *bp++; - break; - case 's': - sp = va_arg(va, unsigned short *); - s = (unsigned) *bp++; - s |= (unsigned) *bp++ << 8; - *sp = s; - break; - case 'l': - lp = va_arg(va, unsigned long *); - l = (unsigned long) *bp++; - l |= (unsigned long) *bp++ << 8; - l |= (unsigned long) *bp++ << 16; - l |= (unsigned long) *bp++ << 24; - *lp = l; - break; - case 'q': - qp = va_arg(va, unsigned long long *); - q = (unsigned long long) *bp++; - q |= (unsigned long long) *bp++ << 8; - q |= (unsigned long long) *bp++ << 16; - q |= (unsigned long long) *bp++ << 24; - q |= (unsigned long long) *bp++ << 32; - q |= (unsigned long long) *bp++ << 40; - q |= (unsigned long long) *bp++ << 48; - q |= (unsigned long long) *bp++ << 56; - *qp = q; - break; - default: - va_end(va); - return -1; - } - } - va_end(va); - - return bp - src; -} diff --git a/lib/scc/newitem.c b/lib/scc/newitem.c @@ -1,12 +0,0 @@ -#include "../../inc/scc.h" - -void -newitem(struct items *items, char *item) -{ - if ((items->n + 1) < items->n) - die("overflow in newitem (%u + 1)", items->n); - - items->s = xrealloc(items->s, (items->n + 1) * sizeof(char **)); - items->s[items->n++] = item; -} - diff --git a/lib/scc/objlst.mk b/lib/scc/objlst.mk @@ -1,16 +0,0 @@ - -LIBSCC-OBJ = $(LIBSCC)/debug.o \ - $(LIBSCC)/die.o \ - $(LIBSCC)/newitem.o \ - $(LIBSCC)/xcalloc.o \ - $(LIBSCC)/xmalloc.o \ - $(LIBSCC)/xrealloc.o \ - $(LIBSCC)/xstrdup.o \ - $(LIBSCC)/alloc.o \ - $(LIBSCC)/casecmp.o \ - $(LIBSCC)/lunpack.o \ - $(LIBSCC)/lpack.o \ - $(LIBSCC)/bunpack.o \ - $(LIBSCC)/bpack.o \ - $(LIBSCC)/wmyro.o \ - $(LIBSCC)/rmyro.o \ diff --git a/lib/scc/rmyro.c b/lib/scc/rmyro.c @@ -1,94 +0,0 @@ -static char sccsid[] = "@(#) ./lib/scc/rmyro.c"; - -#include <assert.h> -#include <stdio.h> -#include <string.h> - -#include "../../inc/scc.h" -#include "../../inc/myro.h" - -int -rdmyrohdr(FILE *fp, struct myrohdr *hdr) -{ - unsigned char buf[MYROHDR_SIZ]; - int len; - - fread(buf, sizeof(buf), 1, fp); - if (ferror(fp)) - return EOF; - len = lunpack(buf, "cccclqqqqq", - hdr->magic+0, hdr->magic+1, - hdr->magic+2, hdr->magic+3, - &hdr->format, - &hdr->entry, - &hdr->strsize, - &hdr->secsize, - &hdr->symsize, - &hdr->relsize); - assert(len == MYROHDR_SIZ); - - return len; -} - -int -rdmyrosec(FILE *fp, struct myrosect *sect) -{ - unsigned char buf[MYROSECT_SIZ]; - int len; - - fread(buf, sizeof(buf), 1, fp); - if (ferror(fp)) - return EOF; - len = lunpack(buf, "lsccqq", - &sect->name, - &sect->flags, - &sect->fill, - &sect->aligment, - &sect->offset, - &sect->len); - assert(len == MYROSECT_SIZ); - - return len; -} - -int -rdmyrosym(FILE *fp, struct myrosym *sym) -{ - unsigned char buf[MYROSYM_SIZ]; - int len; - - fread(buf, sizeof(buf), 1, fp); - if (ferror(fp)) - return EOF; - len = lunpack(buf, "llccqq", - &sym->name, - &sym->type, - &sym->section, - &sym->flags, - &sym->offset, - &sym->len); - assert(len == MYROSYM_SIZ); - - return len; -} - -int -rdmyrorel(FILE *fp, struct myrorel *rel) -{ - unsigned char buf[MYROREL_SIZ]; - int len; - - fread(buf, sizeof(buf), 1, fp); - if (ferror(fp)) - return EOF; - len = lunpack(buf, "lccccq", - &rel->id, - &rel->flags, - &rel->size, - &rel->nbits, - &rel->shift, - &rel->offset); - assert(len == MYROREL_SIZ); - - return len; -} diff --git a/lib/scc/wmyro.c b/lib/scc/wmyro.c @@ -1,86 +0,0 @@ -static char sccsid[] = "@(#) ./lib/scc/wmyro.c"; - -#include <assert.h> -#include <stdio.h> -#include <string.h> - -#include "../../inc/scc.h" -#include "../../inc/myro.h" - -int -wrmyrohdr(FILE *fp, struct myrohdr *hdr) -{ - unsigned char buf[MYROHDR_SIZ]; - int len; - - len = lpack(buf, "cccclqqqqq", - hdr->magic[0], hdr->magic[1], - hdr->magic[2], hdr->magic[3], - hdr->format, - hdr->entry, - hdr->strsize, - hdr->secsize, - hdr->symsize, - hdr->relsize); - assert(MYROHDR_SIZ == len); - fwrite(buf, len, 1, fp); - - return (ferror(fp)) ? EOF : len; -} - -int -wrmyrosec(FILE *fp, struct myrosect *sect) -{ - unsigned char buf[MYROSECT_SIZ]; - int len; - - len = lpack(buf, "lsccqq", - sect->name, - sect->flags, - sect->fill, - sect->aligment, - sect->offset, - sect->len); - assert(MYROSECT_SIZ == len); - fwrite(buf, len, 1, fp); - - return (ferror(fp)) ? EOF : len; -} - -int -wrmyrosym(FILE *fp, struct myrosym *sym) -{ - unsigned char buf[MYROSYM_SIZ]; - int len; - - len = lpack(buf, "llccqq", - sym->name, - sym->type, - sym->section, - sym->flags, - sym->offset, - sym->len); - assert(MYROSYM_SIZ == len); - fwrite(buf, len, 1, fp); - - return (ferror(fp)) ? EOF : len; -} - -int -wrmyrorel(FILE *fp, struct myrorel *rel) -{ - unsigned char buf[MYROREL_SIZ]; - int len; - - len = lpack(buf, "lccccq", - rel->id, - rel->flags, - rel->size, - rel->nbits, - rel->shift, - rel->offset); - assert(MYROREL_SIZ == len); - fwrite(buf, len, 1, fp); - - return (ferror(fp)) ? EOF : len; -} diff --git a/lib/scc/xcalloc.c b/lib/scc/xcalloc.c @@ -1,13 +0,0 @@ -static char sccsid[] = "@(#) ./lib/scc/xcalloc.c"; -#include <stdlib.h> -#include "../../inc/scc.h" - -void * -xcalloc(size_t n, size_t size) -{ - void *p = calloc(n, size); - - if (!p) - die("out of memory"); - return p; -} diff --git a/lib/scc/xmalloc.c b/lib/scc/xmalloc.c @@ -1,13 +0,0 @@ -static char sccsid[] = "@(#) ./lib/scc/xmalloc.c"; -#include <stdlib.h> -#include "../../inc/scc.h" - -void * -xmalloc(size_t size) -{ - void *p = malloc(size); - - if (!p) - die("out of memory"); - return p; -} diff --git a/lib/scc/xrealloc.c b/lib/scc/xrealloc.c @@ -1,13 +0,0 @@ -static char sccsid[] = "@(#) ./lib/scc/xrealloc.c"; -#include <stdlib.h> -#include "../../inc/scc.h" - -void * -xrealloc(void *buff, size_t size) -{ - void *p = realloc(buff, size); - - if (!p) - die("out of memory"); - return p; -} diff --git a/lib/scc/xstrdup.c b/lib/scc/xstrdup.c @@ -1,12 +0,0 @@ -static char sccsid[] = "@(#) ./lib/scc/xstrdup.c"; -#include <string.h> -#include "../../inc/scc.h" - -char * -xstrdup(const char *s) -{ - size_t len = strlen(s) + 1; - char *p = xmalloc(len); - - return memcpy(p, s, len); -} diff --git a/mkdep.sh b/mkdep.sh @@ -1,19 +0,0 @@ -#!/bin/sh - -set -e - -(echo '/^#deps/+;$c' - -for i in `find . -name '*.c'` -do - file=`basename $i | sed 's/\.c$/.o/'` - - dir=`dirname $i | - sed -e 's,^\./,,' -e 's,^\.$,,' -e 's,...*[^/],&/,'` - - sed -n "/#include \"/ s,#include \"\(.*\)\",$dir$file: $dir\1,p" $i -done | -LC_ALL=C sort -s - -echo . -echo w) | ed -s deps.mk diff --git a/nm/Makefile b/nm/Makefile @@ -1,22 +0,0 @@ -.POSIX: - -PROJECTDIR = .. -include $(PROJECTDIR)/rules.mk -include $(LIBSCC)/libdep.mk - -OBJ = main.o coff32.o formats.o - -all: $(BINDIR)/nm - -$(BINDIR)/nm: $(OBJ) $(LIBDIR)/libscc.a - $(CC) $(SCC_LDFLAGS) $(OBJ) -lscc -o $@ - -dep: - $(PROJECTDIR)/mkdep.sh - -clean: - rm -f $(BINDIR)/nm *.o - -distclean: clean - -include deps.mk diff --git a/nm/coff32.c b/nm/coff32.c @@ -1,312 +0,0 @@ -static char sccsid[] = "@(#) ./nm/coff.c"; - -#include <assert.h> -#include <ctype.h> -#include <errno.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "../inc/coff32/filehdr.h" -#include "../inc/coff32/scnhdr.h" -#include "../inc/coff32/syms.h" -#include "../inc/scc.h" -#include "nm.h" - -static int (*unpack)(unsigned char *, char *, ...); -static long strtbl, symtbl, sectbl; -static SCNHDR *sections; -static struct symbol *syms; -static size_t nsect, nsyms; - -static char -typeof(SYMENT *ent) -{ - SCNHDR *sec; - int c; - long flags; - - switch (ent->n_scnum) { - case N_DEBUG: - c = 'n'; - break; - case N_ABS: - c = 'a'; - break; - case N_UNDEF: - c = (ent->n_value != 0) ? 'C' : 'U'; - break; - default: - if (ent->n_scnum > nsect) - die("nm: incorrect section index"); - sec = &sections[ent->n_scnum-1]; - flags = sec->s_flags; - if (flags & STYP_TEXT) - c = 't'; - else if (flags & STYP_DATA) - c = 'd'; - else if (flags & STYP_BSS) - c = 'b'; - else - c = '?'; - break; - } - - if (ent->n_sclass == C_EXT) - c = toupper(c); - - return c; -} - -static char * -getsname(char *fname, FILE *fp, SYMENT *ent) -{ - int c; - size_t len; - char *s, *err; - fpos_t pos; - - if (ent->n_zeroes != 0) { - for (len = 0; len < E_SYMNMLEN && ent->n_name[len]; ++len) - ; - s = xmalloc(len+1); - s[len] = '\0'; - return memcpy(s, ent->n_name, len); - } - - /* TODO: read the string table in memory before reading symbols */ - fgetpos(fp, &pos); - fseek(fp, strtbl, SEEK_SET); - fseek(fp, ent->n_offset, SEEK_CUR); - - if (ferror(fp)) - goto error; - - s = NULL; - for (len = 1; (c = getc(fp)) != EOF; len++) { - s = xrealloc(s, len); - if ((s[len-1] = c) == '\0') - break; - } - if (c == EOF) - goto error; - fsetpos(fp, &pos); - return s; - -error: - err = (!ferror(fp)) ? - "EOF before reading strings" : strerror(errno); - die("nm: %s: %s", fname, err); -} - -static void -getfsym(unsigned char *buff, SYMENT *ent) -{ - int n; - - n = (*unpack)(buff, - "'8lsscc", - &ent->n_name, - &ent->n_value, - &ent->n_scnum, - &ent->n_type, - &ent->n_sclass, - &ent->n_numaux); - assert(n == SYMESZ); -} - -static void -getsymbol(char *fname, FILE *fp, - unsigned char *buff, SYMENT *ent, struct symbol *sym) -{ - char *nam; - - getfsym(buff, ent); - nam = ent->n_name; - if (nam[0] == 0 && nam[1] == 0 && nam[2] == 0 && nam[3] == 0) { - long zero, offset; - - (*unpack)(nam, "ll", &zero, &offset); - ent->n_zeroes = zero; - ent->n_offset = offset; - } - sym->name = getsname(fname, fp, ent); - sym->type = typeof(ent); - sym->value = ent->n_value; - sym->size = (sym->type == 'C') ? ent->n_value : 0; -} - -static void -getsyms(char *fname, char *member, FILE *fp, FILHDR *hdr) -{ - size_t n, i; - unsigned aux; - unsigned char buff[SYMESZ]; - SYMENT ent; - - if (hdr->f_nsyms > SIZE_MAX) - die("nm: %s:Too many symbols\n", member); - - n = hdr->f_nsyms; - syms = xcalloc(sizeof(*syms), n); - - if (fseek(fp, symtbl, SEEK_SET) == EOF) - die("nm: %s:%s", fname, strerror(errno)); - - aux = nsyms = 0; - for (i = 0; i < n; i++) { - if (fread(buff, SYMESZ, 1, fp) != 1) - break; - if (aux > 0) { - aux--; - continue; - } - getsymbol(member, fp, buff, &ent, &syms[nsyms++]); - aux = ent.n_numaux; - } - if (n != i) { - char *err; - - err = (!ferror(fp)) ? - "EOF before reading symbols" : strerror(errno); - die("nm: %s: %s", fname, err); - } -} - -static void -getfsec(unsigned char *buff, SCNHDR *sec) -{ - int n; - - n = (*unpack)(buff, - "'8llllllssl", - sec->s_name, - &sec->s_paddr, - &sec->s_vaddr, - &sec->s_size, - &sec->s_scnptr, - &sec->s_relptr, - &sec->s_lnnoptr, - &sec->s_nrelloc, - &sec->s_nlnno, - &sec->s_flags); - assert(n == SCNHSZ); -} - -static void -getsects(char *fname, char *member, FILE *fp, FILHDR *hdr) -{ - size_t i; - char buff[SCNHSZ]; - - nsect = hdr->f_nscns; - if (nsect == 0) - return; - - if (nsect > SIZE_MAX) - die("nm: %s:Too many sections\n", member); - - if (fseek(fp, sectbl, SEEK_SET) == EOF) - die("nm: %s:%s", member, strerror(errno)); - - sections = xcalloc(sizeof(*sections), nsect); - for (i = 0; i < nsect; i++) { - if (fread(buff, SCNHSZ, 1, fp) != 1) - break; - getfsec(buff, &sections[i]); - } - if (i != nsect) { - char *err; - - err = (!ferror(fp)) ? - "EOF before reading sections" : strerror(errno); - die("nm: %s: %s", fname, err); - } -} - -static void -getfhdr(unsigned char *buff, FILHDR *hdr) -{ - int n; - - n = (*unpack)(buff, - "sslllss", - &hdr->f_magic, - &hdr->f_nscns, - &hdr->f_timdat, - &hdr->f_symptr, - &hdr->f_nsyms, - &hdr->f_opthdr, - &hdr->f_flags); - assert(n == FILHSZ); -} - -static int -nm(char *fname, char *member, FILE *fp) -{ - unsigned char buff[FILHSZ]; - FILHDR hdr; - long pos = ftell(fp); - - if (fread(buff, FILHSZ, 1, fp) != 1) { - if (!ferror(fp)) - return 0; - die("nm: %s: %s", fname, strerror(errno)); - } - - getfhdr(buff, &hdr); - if ((hdr.f_flags & F_SYMS) != 0 || hdr.f_nsyms == 0) { - fprintf(stderr, "nm: %s: no symbols\n", member); - return 1; - } - - /* TODO: Check overflow */ - strtbl = pos + hdr.f_symptr + hdr.f_nsyms* SYMESZ; - symtbl = pos + hdr.f_symptr; - sectbl = pos + FILHSZ + hdr.f_opthdr; - - getsects(fname, member, fp, &hdr); - getsyms(fname, member, fp, &hdr); - printsyms(fname, member, syms, nsyms); - - free(sections); - free(syms); - return 1; -} - -static int -probe(char *fname, char *member, FILE *fp) -{ - int c; - int c1, c2; - fpos_t pos; - unsigned short magic; - - fgetpos(fp, &pos); - c1 = getc(fp); - c2 = getc(fp); - fsetpos(fp, &pos); - - if (ferror(fp)) - die("nm: %s: %s", fname, strerror(errno)); - - if (c1 == EOF || c2 == EOF) - return 0; - magic = c1 | c2 << 8; - - switch (magic) { - case COFF_I386MAGIC: - case COFF_Z80MAGIC: - unpack = lunpack; - return 1; - default: - unpack = NULL; - return 0; - } -} - -struct objfile coff32 = { - .probe = probe, - .nm = nm, -}; diff --git a/nm/deps.mk b/nm/deps.mk @@ -1,12 +0,0 @@ - -#deps -coff32.o: ../inc/coff32/filehdr.h -coff32.o: ../inc/coff32/scnhdr.h -coff32.o: ../inc/coff32/syms.h -coff32.o: ../inc/scc.h -coff32.o: nm.h -formats.o: nm.h -main.o: ../inc/ar.h -main.o: ../inc/arg.h -main.o: ../inc/scc.h -main.o: nm.h diff --git a/nm/formats.c b/nm/formats.c @@ -1,13 +0,0 @@ -static char sccsid[] = "@(#) ./nm/probe.c"; - -#include <stdio.h> - -#include "nm.h" - -/* TODO: Autogenerate this file */ -struct objfile coff32; - -struct objfile *formats[] = { - &coff32, - NULL, -}; diff --git a/nm/main.c b/nm/main.c @@ -1,272 +0,0 @@ -static char sccsid[] = "@(#) ./nm/main.c"; - -#include <ctype.h> -#include <errno.h> -#include <limits.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "../inc/arg.h" -#include "../inc/scc.h" -#include "../inc/ar.h" -#include "nm.h" - -char *argv0; -static int radix = 16; -static int Pflag; -static int Aflag; -static int vflag; -static int gflag; -static int uflag; -static int arflag; - -static int -object(char *fname, char *member, FILE *fp) -{ - extern struct objfile *formats[]; - struct objfile **p, *obj; - void *data; - - for (p = formats; *p; ++p) { - obj = *p; - if ((*obj->probe)(fname, member, fp)) - break; - } - if (*p == NULL) - return 0; - return (*obj->nm)(fname, member, fp); -} - -static char * -getfname(struct ar_hdr *hdr, char *dst) -{ - char *p; - int i; - - memcpy(dst, hdr->ar_name, SARNAM); - dst[SARNAM] = '\0'; - - for (i = SARNAM-1; i >= 0; i--) { - if (dst[i] != ' ' && dst[i] != '/') - break; - dst[i] = '\0'; - } - return dst; -} - -static void -ar(char *fname, FILE *fp) -{ - struct ar_hdr hdr; - long pos, siz; - char member[SARNAM+1]; - - arflag = 1; - if (fseek(fp, SARMAG, SEEK_SET) == EOF) - goto file_error; - - while (fread(&hdr, sizeof(hdr), 1, fp) == 1) { - pos = ftell(fp); - if (strncmp(hdr.ar_fmag, ARFMAG, sizeof(hdr.ar_fmag))) - goto corrupted; - - siz = 0; - sscanf(hdr.ar_size, "%10ld", &siz); - if (siz == 0) - goto corrupted; - - if (siz & 1) - siz++; - if (pos == -1 || pos > LONG_MAX - siz) - die("nm: %s: overflow in size of archive", fname); - pos += siz; - - getfname(&hdr, member); - if (!object(fname, member, fp)) { - fprintf(stderr, - "nm: skipping member %s in archive %s\n", - member, fname); - } - if (fseek(fp, pos, SEEK_SET) == EOF) - goto file_error; - } - if (ferror(fp)) - goto file_error; - return; - -corrupted: - die("nm: %s: corrupted archive", fname); -file_error: - die("nm: %s: %s", fname, strerror(errno)); -} - -static int -archive(char *fname, FILE *fp) -{ - char magic[SARMAG]; - fpos_t pos; - - fgetpos(fp, &pos); - fread(magic, SARMAG, 1, fp); - fsetpos(fp, &pos); - - if (ferror(fp)) - die("nm: %s: %s", fname, strerror(errno)); - if (strncmp(magic, ARMAG, SARMAG) != 0) - return 0; - - ar(fname, fp); - return 1; -} - -static void -printsym(char *file, char *member, struct symbol *sym) -{ - char *fmt; - int type = sym->type; - - if (type == '?') - return; - - if (uflag && type != 'U') - return; - - if (gflag && !isupper(type)) - return; - - if (Aflag) - printf((arflag) ? "%s[%s]: " : "%s: ", file, member); - if (Pflag) { - printf("%s %c", sym->name, sym->type); - if (type != 'U') { - if (radix == 8) - fmt = " %016.16llo %lo"; - else if (radix == 10) - fmt = " %016.16llu %lu"; - else - fmt = " %016.16llx %lx"; - printf(fmt, sym->value, sym->size); - } - } else { - if (type == 'U') - fmt = " "; - else if (radix == 8) - fmt = "%016.16llo"; - else if (radix == 10) - fmt = "%016.16lld"; - else - fmt = "%016.16llx"; - printf(fmt, sym->value); - printf(" %c %s", sym->type, sym->name); - } - putchar('\n'); -} - -static int -cmp(const void *p1, const void *p2) -{ - const struct symbol *s1 = p1, *s2 = p2; - - if (vflag) { - if (s1->value > s2->value) - return 1; - if (s1->value < s2->value) - return -1; - if (s1->type == 'U' && s2->type == 'U') - return 0; - if (s1->type == 'U') - return -1; - if (s2->type == 'U') - return 1; - return 0; - } else { - return strcmp(s1->name, s2->name); - } -} - -void -printsyms(char *file, char *member, struct symbol *syms, size_t nsyms) -{ - qsort(syms, nsyms, sizeof(*syms), cmp); - - while (nsyms--) - printsym(file, member, syms++); -} - -static void -doit(char *fname) -{ - FILE *fp; - - arflag = 0; - - if ((fp = fopen(fname, "rb")) == NULL) - die("nm: %s: %s", fname, strerror(errno)); - - if (!object(fname, fname, fp) && !archive(fname, fp)) - die("nm: %s: File format not recognized", fname); - - if (ferror(fp)) - die("nm: %s: %s", fname, strerror(errno)); - - fclose(fp); -} - -static void -usage(void) -{ - fputs("nm [-APv][ -g| -u][-t format] [file...]\n", stderr); - exit(1); -} - -int -main(int argc, char *argv[]) -{ - char *t; - - ARGBEGIN { - case 'P': - Pflag = 1; - break; - case 'A': - Aflag = 1; - break; - case 'g': - gflag = 1; - break; - case 'u': - uflag = 1; - break; - case 'v': - vflag = 1; - break; - case 't': - t = EARGF(usage()); - if (!strcmp(t, "o")) - radix = 8; - else if (!strcmp(t, "d")) - radix = 10; - else if (!strcmp(t, "x")) - radix = 16; - else - usage(); - break; - default: - usage(); - } ARGEND - - if (argc == 0) { - doit("a.out"); - } else { - for ( ; *argv; ++argv) - doit(*argv); - } - - fflush(stdout); - if (ferror(stdout)) - die("nm: error writing in output"); - - return 0; -} diff --git a/nm/nm.h b/nm/nm.h @@ -1,14 +0,0 @@ -struct symbol { - char *name; - int type; - unsigned long long value; - unsigned long size; -}; - -struct objfile { - int (*probe)(char *fname, char *member, FILE *fp); - int (*nm)(char *fname, char *member, FILE *fp); -}; - -/* main.c */ -extern void printsyms(char *, char *, struct symbol *, size_t ); diff --git a/objdump/Makefile b/objdump/Makefile @@ -1,20 +0,0 @@ -.POSIX: - -PROJECTDIR = .. -include $(PROJECTDIR)/rules.mk -include $(LIBSCC)/libdep.mk - -OBJ = main.o - -all: $(BINDIR)/objdump - -$(BINDIR)/objdump: $(OBJ) $(LIBDIR)/libscc.a - $(CC) $(SCC_LDFLAGS) $(OBJ) -lscc -o $@ - -dep: - $(PROJECTDIR)/mkdep.sh - -clean: - rm -f $(BINDIR)/objdump *.o - -include deps.mk diff --git a/objdump/deps.mk b/objdump/deps.mk @@ -1,4 +0,0 @@ -#deps -main.o: ../inc/arg.h -main.o: ../inc/myro.h -main.o: ../inc/scc.h diff --git a/objdump/main.c b/objdump/main.c @@ -1,333 +0,0 @@ -#include <errno.h> -#include <limits.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "../inc/arg.h" -#include "../inc/scc.h" -#include "../inc/myro.h" - -char *argv0; -static char *strings; -static size_t strsiz; - -struct obj_info { - char *fname; - FILE *fp; - struct myrohdr hdr; - fpos_t strpos; - fpos_t secpos; - fpos_t sympos; - fpos_t relpos; - fpos_t datapos; -}; - -static char * -getstring(unsigned long off) -{ - size_t n; - - if ((int32_t) off == -1) - return ""; - if (off < SIZE_MAX) { - for (n = off; n < strsiz && strings[n]; ++n) - ; - if (n < strsiz) - return &strings[off]; - } - fprintf(stderr, "objdump: wrong string offset %lu\n", off); - return ""; -} - -static int -printhdr(struct obj_info *obj) -{ - struct myrohdr *hdr = &obj->hdr; - - printf("header:\n" - " magic: %02x %02x %02x %02x \"%4.4s\"\n" - " format: %lu (\"%s\")\n" - " entry: %llu\n" - " string table size: %llu\n" - " section table size: %llu\n" - " symbol table size: %llu\n" - " relocation table size: %llu\n", - hdr->magic[0], hdr->magic[1], - hdr->magic[2], hdr->magic[3], - hdr->magic, - hdr->format, getstring(hdr->format), - hdr->entry, - hdr->strsize, - hdr->secsize, - hdr->symsize, - hdr->relsize); - return 0; -} - -static int -printstrings(struct obj_info *obj) -{ - size_t off, begin;; - char *s = NULL; - - puts("strings:"); - for (off = 0; off < strsiz; off++) { - if (s == NULL) { - s = &strings[off]; - begin = off; - } - if (strings[off] == '\0') { - printf(" [%zd] \"%s\"\n", begin, s); - s = NULL; - } - } - return 0; -} - -static char * -sectflags(struct myrosect *sec) -{ - static char flags[10]; - char *s = flags + sizeof(flags); - - if (sec->flags & MYROSEC_LOAD) - *--s = 'L'; - if (sec->flags & MYROSEC_FILE) - *--s = 'F'; - if (sec->flags & MYROSEC_ABS) - *--s = 'A'; - if (sec->flags & MYROSEC_EXEC) - *--s = 'X'; - if (sec->flags & MYROSEC_WRITE) - *--s = 'W'; - if (sec->flags & MYROSEC_READ) - *--s = 'R'; - return s; -} - -static int -printsections(struct obj_info *obj) -{ - unsigned long long n, i; - struct myrosect sect; - struct myrohdr *hdr = &obj->hdr; - - printf("sections:\n" - " [Nr]\t%s\t%-16s\t%-16s\t%s\t%s\t%s\n", - "Name", - "Offset", - "Size", - "Fill", - "Align", - "Flags"); - - n = hdr->secsize / MYROSECT_SIZ; - for (i = 0; i < n; ++i) { - if (rdmyrosec(obj->fp, &sect) < 0) - return -1; - printf(" [%2llu]\t%s\t%016llX\t%016llX\t%02X\t%u\t%s\n", - i, - getstring(sect.name), - sect.offset, - sect.len, - sect.fill, - sect.aligment, - sectflags(&sect)); - } - return 0; -} - -static char * -symflags(struct myrosym *sym) -{ - static char flags[10]; - char *s = flags + sizeof(flags); - - if (sym->flags & MYROSYM_COMMON) - *--s = 'C'; - if (sym->flags & MYROSYM_EXTERN) - *--s = 'G'; - if (sym->flags & MYROSYM_UNDEF) - *s-- = 'U'; - return s; -} - -static int -printsymbols(struct obj_info *obj) -{ - unsigned long long n, i; - struct myrosym sym; - struct myrohdr *hdr = &obj->hdr; - - printf("symbols:\n" - " [Nr]\t%s\t%-16s\t%s\t%s\t%s\t%s\n", - "Name", - "Value", - "Section", - "Flags", - "Size", - "Type"); - n = hdr->symsize / MYROSYM_SIZ; - for (i = 0; i < n; ++i) { - if (rdmyrosym(obj->fp, &sym) < 0) - return -1; - printf(" [%2llu]\t%s\t%016llX\t%u\t%s\t%llu\t%s\n", - i, - getstring(sym.name), - sym.offset, - sym.section, - symflags(&sym), - sym.len, - getstring(sym.type)); - } - return 0; -} - -static int -printrelocs(struct obj_info *obj) -{ - unsigned long long n, i; - struct myrorel rel; - struct myrohdr *hdr = &obj->hdr; - - printf("relocs:\n" - " [Nr]\t%-16s\tType\tId\tSize\tNbits\tShift\n", - "Offset"); - n = hdr->relsize / MYROREL_SIZ; - for (i = 0; i < n; ++i) { - if (rdmyrorel(obj->fp, &rel) < 0) - return -1; - printf(" [%2llu]\t%016llX\t%s\t%lu\t%u\t%u\t%u\n", - i, - rel.offset, - (rel.id & 1<<31) ? "section" : "symbol", - rel.id & ~(1<<31), - rel.size, - rel.nbits, - rel.shift); - } - return 0; -} - -static int -printdata(struct obj_info *obj) -{ - unsigned long long off; - int c, i, j; - - puts("data:"); - for (off = 0; ; off += 32) { - printf(" %016llX:", off); - for (i = 0; i < 2; i++) { - for (j = 0; j < 8; j++) { - if ((c = getc(obj->fp)) == EOF) - goto exit_loop; - printf(" %02X", c); - } - putchar('\t'); - } - putchar('\n'); - } - -exit_loop: - putchar('\n'); - return (ferror(obj->fp)) ? -1 : 0; -} - -void -dump(char *fname, FILE *fp) -{ - struct obj_info obj; - struct myrohdr *hdr; - - obj.fname = fname; - obj.fp = fp; - hdr = &obj.hdr; - - if (rdmyrohdr(obj.fp, hdr) < 0) - goto wrong_file; - if (strncmp(hdr->magic, MYROMAGIC, MYROMAGIC_SIZ)) { - fprintf(stderr, - "objdump: %s: File format not recognized\n", - fname); - return; - } - puts(fname); - if (hdr->strsize > SIZE_MAX) { - fprintf(stderr, - "objdump: %s: overflow in header\n", - fname); - return; - } - strsiz = hdr->strsize; - - if (strsiz > 0) { - strings = xmalloc(strsiz); - fread(strings, strsiz, 1, fp); - if (feof(fp)) - goto wrong_file; - } - - if (printhdr(&obj) < 0) - goto wrong_file; - if (printstrings(&obj) < 0) - goto wrong_file; - if (printsections(&obj) < 0) - goto wrong_file; - if (printsymbols(&obj) < 0) - goto wrong_file; - if (printrelocs(&obj) < 0) - goto wrong_file; - if (printdata(&obj) < 0) - goto wrong_file; - return; - -wrong_file: - fprintf(stderr, - "objdump: %s: %s\n", - fname, strerror(errno)); -} - -void -doit(char *fname) -{ - FILE *fp; - - if ((fp = fopen(fname, "rb")) == NULL) { - fprintf(stderr, "objdump: %s: %s\n", fname, strerror(errno)); - return; - } - dump(fname, fp); - fclose(fp); -} - -void -usage(void) -{ - fputs("usage: objdump file ...\n", stderr); - exit(1); -} - -int -main(int argc, char *argv[]) -{ - ARGBEGIN { - default: - usage(); - } ARGEND - - if (argc == 0) - doit("a.out"); - else while (*argv) { - free(strings); - strings = NULL; - doit(*argv++); - } - - if (fclose(stdout) == EOF) - die("objdump: stdout: %s", strerror(errno)); - - return 0; -} diff --git a/root/bin/README b/root/bin/README @@ -1 +0,0 @@ -This is a placeholder for VCS diff --git a/root/include/scc/assert.h b/root/include/scc/assert.h @@ -1,8 +0,0 @@ -extern void __assert(char *exp, char *file, long line); - -#undef assert -#ifndef NDEBUG -# define assert(exp) ((exp) ? (void) 0 : __assert(#exp, __FILE__, __LINE__)) -#else -# define assert(exp) ((void)0) -#endif diff --git a/root/include/scc/bits/.gitignore b/root/include/scc/bits/.gitignore @@ -1 +0,0 @@ -errno.h diff --git a/root/include/scc/bits/amd64/arch/limits.h b/root/include/scc/bits/amd64/arch/limits.h @@ -1,18 +0,0 @@ -#define CHAR_BIT 8 -#define SCHAR_MAX 0x7F -#define SCHAR_MIN (-SCHAR_MIN-1) -#define CHAR_MAX 0x7F -#define CHAR_MIN (-CHAR_MAX-1) -#define UCHAR_MAX 0xFF -#define SHRT_MAX 0x7FFF -#define SHRT_MIN (-SHRT_MAX-1) -#define USHRT_MAX 0xFFFF -#define INT_MAX 0x7FFFFFFF -#define INT_MIN (-INT_MAX-1) -#define UINT_MAX 0xFFFFFFFF -#define LONG_MAX 0x7FFFFFFFFFFFFFFF -#define LONG_MIN (-LONG_MAX-1) -#define ULONG_MAX 0xFFFFFFFFFFFFFFFF -#define LLONG_MAX 0x7FFFFFFFFFFFFFFF -#define LLONG_MIN (-LLONG_MAX-1) -#define ULLONG_MAX 0xFFFFFFFFFFFFFFFF diff --git a/root/include/scc/bits/amd64/arch/setjmp.h b/root/include/scc/bits/amd64/arch/setjmp.h @@ -1 +0,0 @@ -typedef unsigned long long jmp_buf[8]; diff --git a/root/include/scc/bits/amd64/arch/stddef.h b/root/include/scc/bits/amd64/arch/stddef.h @@ -1,14 +0,0 @@ -#ifndef _SIZET -typedef unsigned long size_t; -#define _SIZET -#endif - -#ifndef _WCHAR_T -typedef int wchar_t; -#define _WCHAR_T -#endif - -#ifndef _PTRDIFF_T -typedef long ptrdiff_t; -#define _PTRDIFF_T -#endif diff --git a/root/include/scc/bits/amd64/arch/stdint.h b/root/include/scc/bits/amd64/arch/stdint.h @@ -1,102 +0,0 @@ -#define INT8_MAX 0x7F -#define INT8_MIN (-INT8_MAX-1) -#define UINT8_MAX 0xFF - -#define INT16_MAX 0x7FFF -#define INT16_MIN (-INT16_MAX-1) -#define UINT16_MAX 0xFFFF - -#define INT32_MAX 0x7FFFFFFF -#define INT32_MIN (-INT32_MAX-1) -#define UINT32_MAX 0xFFFFFFFF - -#define INT64_MAX 0x7FFFFFFFFFFFFFFF -#define INT64_MIN (-INT64_MAX-1) -#define UINT64_MAX 0xFFFFFFFFFFFFFFFF - -#define INT_LEAST8_MIN INT8_MIN -#define INT_LEAST8_MAX INT8_MAX -#define UINT_LEAST8_MAX UINT8_MAX - -#define INT_LEAST16_MIN INT16_MIN -#define INT_LEAST16_MAX INT16_MAX -#define UINT_LEAST16_MAX UINT16_MAX - -#define INT_LEAST32_MIN INT32_MIN -#define INT_LEAST32_MAX INT32_MAX -#define UINT_LEAST32_MAX UINT32_MAX - -#define INT_LEAST64_MIN INT64_MIN -#define INT_LEAST64_MAX INT64_MAX -#define UINT_LEAST64_MAX UINT64_MAX - -#define INT_FAST8_MIN INT32_MIN -#define INT_FAST8_MAX INT32_MAX -#define UINT_FAST8_MAX UINT32_MAX - -#define INT_FAST16_MIN INT32_MIN -#define INT_FAST16_MAX INT32_MAX -#define UINT_FAST16_MAX UINT32_MAX - -#define INT_FAST32_MIN INT32_MIN -#define INT_FAST32_MAX INT32_MAX -#define UINT_FAST32_MAX UINT32_MAX - -#define INT_FAST64_MIN INT64_MIN -#define INT_FAST64_MAX INT64_MAX -#define UINT_FAST64_MAX UINT64_MAX - -#define INTPTR_MIN INT64_MIN -#define INTPTR_MAX INT64_MAX -#define UINTPTR_MAX UINT64_MAX - -#define INTMAX_MIN INT64_MIN -#define INTMAX_MAX INT64_MAX -#define UINTMAX_MAX UINT64_MAX - -#define PTRDIFF_MIN INT64_MIN -#define PTRDIFF_MAX INT64_MAX - -#define SIG_ATOMIC_MIN INT32_MIN -#define SIG_ATOMIC_MAX INT32_MAX - -#define SIZE_MAX UINT64_MAX - -#define WCHAR_MIN INT32_MIN -#define WCHAR_MAX INT32_MAX - -typedef signed char int8_t; -typedef short int16_t; -typedef int int32_t; -typedef long int64_t; - -typedef unsigned char uint8_t; -typedef unsigned short uint16_t; -typedef unsigned uint32_t; -typedef unsigned long uint64_t; - -typedef signed char int8_least_t; -typedef short int16_least_t; -typedef int int32_least_t; -typedef long int64_least_t; - -typedef unsigned char uint8_least_t; -typedef unsigned short uint16_least_t; -typedef unsigned uint32_least_t; -typedef unsigned long uint64_least_t; - -typedef int int8_fast_t; -typedef int int16_fast_t; -typedef int int32_fast_t; -typedef long int64_fast_t; - -typedef unsigned uint8_fast_t; -typedef unsigned uint16_fast_t; -typedef unsigned uint32_fast_t; -typedef unsigned long uint64_fast_t; - -typedef long intptr_t; -typedef unsigned long uintptr_t; - -typedef long intmax_t; -typedef unsigned long uintmax_t; diff --git a/root/include/scc/bits/amd64/arch/stdio.h b/root/include/scc/bits/amd64/arch/stdio.h @@ -1,15 +0,0 @@ -#ifndef _SIZET -typedef unsigned long size_t; -#define _SIZET -#endif - -#define BUFSIZ 512 -#define FILENAME_MAX 256 -#define FOPEN_MAX 16 - -#define TMP_MAX 25 -#define L_tmpnam 256 - -#define _TMPNAME "/tmp/tmp.0000000" - -typedef int fpos_t; diff --git a/root/include/scc/bits/amd64/arch/stdlib.h b/root/include/scc/bits/amd64/arch/stdlib.h @@ -1,14 +0,0 @@ -#ifndef _SIZET -typedef unsigned long size_t; -#define _SIZET -#endif - -#define EXIT_FAILURE 1 -#define EXIT_SUCCESS 0 - -#ifndef _WCHAR_T -typedef int wchar_t; -#define _WCHAR_T -#endif - -#define _ALIGNTYPE long double diff --git a/root/include/scc/bits/amd64/arch/string.h b/root/include/scc/bits/amd64/arch/string.h @@ -1,5 +0,0 @@ -#ifndef _SIZET -typedef unsigned long size_t; -#endif - -#define __NUMCHARS 128 -\ No newline at end of file diff --git a/root/include/scc/bits/amd64/arch/time.h b/root/include/scc/bits/amd64/arch/time.h @@ -1,8 +0,0 @@ -#ifndef _SIZET -typedef unsigned long size_t; -#define _SIZET -#endif - -#define _MAXYEAR 9999 - -typedef long int time_t; diff --git a/root/include/scc/bits/arm32/arch/limits.h b/root/include/scc/bits/arm32/arch/limits.h @@ -1,18 +0,0 @@ -#define CHAR_BIT 8 -#define SCHAR_MAX 0x7F -#define SCHAR_MIN (-SCHAR_MIN - 1) -#define CHAR_MAX 0x7F -#define CHAR_MIN (-CHAR_MAX - 1) -#define UCHAR_MAX 0xFF -#define SHRT_MAX 0x7FFF -#define SHRT_MIN (-SHRT_MAX - 1) -#define USHRT_MAX 0xFFFF -#define INT_MAX 0x7FFFFFFF -#define INT_MIN (-INT_MAX - 1) -#define UINT_MAX 0xFFFFFFFF -#define LONG_MAX 0x7FFFFFFF -#define LONG_MIN (-LONG_MAX - 1) -#define ULONG_MAX 0xFFFFFFFF -#define LLONG_MAX 0x7FFFFFFFFFFFFFFF -#define LLONG_MIN (-LLONG_MAX - 1) -#define ULLONG_MAX 0xFFFFFFFFFFFFFFFF diff --git a/root/include/scc/bits/arm32/arch/setjmp.h b/root/include/scc/bits/arm32/arch/setjmp.h @@ -1 +0,0 @@ -typedef unsigned long jmp_buf[10]; diff --git a/root/include/scc/bits/arm32/arch/stddef.h b/root/include/scc/bits/arm32/arch/stddef.h @@ -1,9 +0,0 @@ -#ifndef SIZET_ -typedef unsigned int size_t; -#define SIZET_ -#endif - -#ifndef _PTRDIFF_T -typedef long ptrdiff_t; -#define _PTRDIFF_T -#endif diff --git a/root/include/scc/bits/arm32/arch/stdint.h b/root/include/scc/bits/arm32/arch/stdint.h @@ -1,96 +0,0 @@ -#define INT8_MAX 0x7F -#define INT8_MIN (-INT8_MAX - 1) -#define UINT8_MAX 0xFF - -#define INT16_MAX 0x7FFF -#define INT16_MIN (-INT16_MAX - 1) -#define UINT16_MAX 0xFFFF - -#define INT32_MAX 0x7FFFFFFF -#define INT32_MIN (-INT32_MAX - 1) -#define UINT32_MAX 0xFFFFFFFF - -#define INT64_MAX 0x7FFFFFFFFFFFFFFF -#define INT64_MIN (-INT64_MAX - 1) -#define UINT64_MAX 0xFFFFFFFFFFFFFFFF - -#define INT_LEAST8_MIN INT8_MIN -#define INT_LEAST8_MAX INT8_MAX -#define UINT_LEAST8_MAX UINT8_MAX - -#define INT_LEAST16_MIN INT16_MIN -#define INT_LEAST16_MAX INT16_MAX -#define UINT_LEAST16_MAX UINT16_MAX - -#define INT_LEAST32_MIN INT32_MIN -#define INT_LEAST32_MAX INT32_MAX -#define UINT_LEAST32_MAX UINT32_MAX - -#define INT_LEAST64_MIN INT64_MIN -#define INT_LEAST64_MAX INT64_MAX -#define UINT_LEAST64_MAX UINT64_MAX - -#define INT_FAST8_MIN INT32_MIN -#define INT_FAST8_MAX INT32_MAX -#define UINT_FAST8_MAX UINT32_MAX - -#define INT_FAST16_MIN INT32_MIN -#define INT_FAST16_MAX INT32_MAX -#define UINT_FAST16_MAX UINT32_MAX - -#define INT_FAST32_MIN INT32_MIN -#define INT_FAST32_MAX INT32_MAX -#define UINT_FAST32_MAX UINT32_MAX - -#define INT_FAST64_MIN INT64_MIN -#define INT_FAST64_MAX INT64_MAX -#define UINT_FAST64_MAX UINT64_MAX - -#define INTPTR_MIN INT32_MIN -#define INTPTR_MAX INT32_MAX -#define UINTPTR_MAX UINT32_MAX - -#define INTMAX_MIN INT64_MIN -#define INTMAX_MAX INT64_MAX -#define UINTMAX_MAX UINT64_MAX - -#define PTRDIFF_MIN INT32_MIN -#define PTRDIFF_MAX INT32_MAX - -#define SIZE_MAX UINT32_MAX - -typedef signed char int8_t; -typedef short int16_t; -typedef int int32_t; -typedef long long int64_t; - -typedef unsigned char uint8_t; -typedef unsigned short uint16_t; -typedef unsigned int uint32_t; -typedef unsigned long long uint64_t; - -typedef signed char int8_least_t; -typedef short int16_least_t; -typedef int int32_least_t; -typedef long long int64_least_t; - -typedef unsigned char uint8_least_t; -typedef unsigned short uint16_least_t; -typedef unsigned int uint32_least_t; -typedef unsigned long long uint64_least_t; - -typedef int int8_fast_t; -typedef int int16_fast_t; -typedef int int32_fast_t; -typedef long long int64_fast_t; - -typedef unsigned int uint8_fast_t; -typedef unsigned int uint16_fast_t; -typedef unsigned int uint32_fast_t; -typedef unsigned long long uint64_fast_t; - -typedef long intptr_t; -typedef unsigned long uintptr_t; - -typedef long long intmax_t; -typedef unsigned long long uintmax_t; diff --git a/root/include/scc/bits/arm32/arch/stdio.h b/root/include/scc/bits/arm32/arch/stdio.h @@ -1,15 +0,0 @@ -#ifndef _SIZET -typedef unsigned int size_t; -#define _SIZET -#endif - -#define BUFSIZ 512 -#define FILENAME_MAX 256 -#define FOPEN_MAX 16 - -#define TMP_MAX 25 -#define L_tmpnam 256 - -#define _TMPNAME "/tmp/tmp.0000000" - -typedef int fpos_t; diff --git a/root/include/scc/bits/arm32/arch/stdlib.h b/root/include/scc/bits/arm32/arch/stdlib.h @@ -1,14 +0,0 @@ -#ifndef SIZET_ -typedef unsigned int size_t; -#define SIZET_ -#endif - -#define EXIT_FAILURE 1 -#define EXIT_SUCCESS 0 - -#ifndef _WCHAR_T -typedef int wchar_t; // TODO -#define _WCHAR_T -#endif - -#define _ALIGNTYPE long double diff --git a/root/include/scc/bits/arm32/arch/string.h b/root/include/scc/bits/arm32/arch/string.h @@ -1,6 +0,0 @@ -#ifndef SIZET_ -typedef unsigned int size_t; -#define SIZET_ -#endif - -#define __NUMCHARS 128 diff --git a/root/include/scc/bits/arm32/arch/time.h b/root/include/scc/bits/arm32/arch/time.h @@ -1,8 +0,0 @@ -#ifndef _SIZET -typedef unsigned int size_t; -#define _SIZET -#endif - -#define _MAXYEAR 9999 - -typedef long int time_t; diff --git a/root/include/scc/bits/arm64/arch/limits.h b/root/include/scc/bits/arm64/arch/limits.h @@ -1,18 +0,0 @@ -#define CHAR_BIT 8 -#define SCHAR_MAX 0x7F -#define SCHAR_MIN (-SCHAR_MIN - 1) -#define CHAR_MAX 0x7F -#define CHAR_MIN (-CHAR_MAX - 1) -#define UCHAR_MAX 0xFF -#define SHRT_MAX 0x7FFF -#define SHRT_MIN (-SHRT_MAX - 1) -#define USHRT_MAX 0xFFFF -#define INT_MAX 0x7FFFFFFF -#define INT_MIN (-INT_MAX - 1) -#define UINT_MAX 0xFFFFFFFF -#define LONG_MAX 0x7FFFFFFFFFFFFFFF -#define LONG_MIN (-LONG_MAX - 1) -#define ULONG_MAX 0xFFFFFFFFFFFFFFFF -#define LLONG_MAX 0x7FFFFFFFFFFFFFFF -#define LLONG_MIN (-LLONG_MAX - 1) -#define ULLONG_MAX 0xFFFFFFFFFFFFFFFF diff --git a/root/include/scc/bits/arm64/arch/setjmp.h b/root/include/scc/bits/arm64/arch/setjmp.h @@ -1 +0,0 @@ -typedef unsigned long long jmp_buf[22]; diff --git a/root/include/scc/bits/arm64/arch/stddef.h b/root/include/scc/bits/arm64/arch/stddef.h @@ -1,9 +0,0 @@ -#ifndef SIZET_ -typedef unsigned long size_t; -#define SIZET_ -#endif - -#ifndef _PTRDIFF_T -typedef long ptrdiff_t; -#define _PTRDIFF_T -#endif diff --git a/root/include/scc/bits/arm64/arch/stdint.h b/root/include/scc/bits/arm64/arch/stdint.h @@ -1,96 +0,0 @@ -#define INT8_MAX 0x7F -#define INT8_MIN (-INT8_MAX - 1) -#define UINT8_MAX 0xFFU - -#define INT16_MAX 0x7FFF -#define INT16_MIN (-INT16_MAX - 1) -#define UINT16_MAX 0xFFFFU - -#define INT32_MAX 0x7FFFFFFF -#define INT32_MIN (-INT32_MAX - 1) -#define UINT32_MAX 0xFFFFFFFF - -#define INT64_MAX 0x7FFFFFFFFFFFFFFF -#define INT64_MIN (-INT64_MAX - 1) -#define UINT64_MAX 0xFFFFFFFFFFFFFFFF - -#define INT_LEAST8_MIN INT8_MIN -#define INT_LEAST8_MAX INT8_MAX -#define UINT_LEAST8_MAX UINT8_MAX - -#define INT_LEAST16_MIN INT16_MIN -#define INT_LEAST16_MAX INT16_MAX -#define UINT_LEAST16_MAX UINT16_MAX - -#define INT_LEAST32_MIN INT32_MIN -#define INT_LEAST32_MAX INT32_MAX -#define UINT_LEAST32_MAX UINT32_MAX - -#define INT_LEAST64_MIN INT64_MIN -#define INT_LEAST64_MAX INT64_MAX -#define UINT_LEAST64_MAX UINT64_MAX - -#define INT_FAST8_MIN INT32_MIN -#define INT_FAST8_MAX INT32_MAX -#define UINT_FAST8_MAX UINT32_MAX - -#define INT_FAST16_MIN INT32_MIN -#define INT_FAST16_MAX INT32_MAX -#define UINT_FAST16_MAX UINT32_MAX - -#define INT_FAST32_MIN INT32_MIN -#define INT_FAST32_MAX INT32_MAX -#define UINT_FAST32_MAX UINT32_MAX - -#define INT_FAST64_MIN INT64_MIN -#define INT_FAST64_MAX INT64_MAX -#define UINT_FAST64_MAX UINT64_MAX - -#define INTPTR_MIN INT64_MIN -#define INTPTR_MAX INT64_MAX -#define UINTPTR_MAX UINT64_MAX - -#define INTMAX_MIN INT64_MIN -#define INTMAX_MAX INT64_MAX -#define UINTMAX_MAX UINT64_MAX - -#define PTRDIFF_MIN INT64_MIN -#define PTRDIFF_MAX INT64_MAX - -#define SIZE_MAX UINT64_MAX - -typedef signed char int8_t; -typedef short int16_t; -typedef int int32_t; -typedef long long int64_t; - -typedef unsigned char uint8_t; -typedef unsigned short uint16_t; -typedef unsigned int uint32_t; -typedef unsigned long long uint64_t; - -typedef signed char int8_least_t; -typedef short int16_least_t; -typedef int int32_least_t; -typedef long long int64_least_t; - -typedef unsigned char uint8_least_t; -typedef unsigned short uint16_least_t; -typedef unsigned int uint32_least_t; -typedef unsigned long long uint64_least_t; - -typedef int int8_fast_t; -typedef int int16_fast_t; -typedef int int32_fast_t; -typedef long long int64_fast_t; - -typedef unsigned int uint8_fast_t; -typedef unsigned int uint16_fast_t; -typedef unsigned int uint32_fast_t; -typedef unsigned long long uint64_fast_t; - -typedef long intptr_t; -typedef unsigned long uintptr_t; - -typedef long intmax_t; -typedef unsigned long uintmax_t; diff --git a/root/include/scc/bits/arm64/arch/stdio.h b/root/include/scc/bits/arm64/arch/stdio.h @@ -1,15 +0,0 @@ -#ifndef _SIZET -typedef unsigned long size_t; -#define _SIZET -#endif - -#define BUFSIZ 512 -#define FILENAME_MAX 256 -#define FOPEN_MAX 16 - -#define TMP_MAX 25 -#define L_tmpnam 256 - -#define _TMPNAME "/tmp/tmp.0000000" - -typedef int fpos_t; diff --git a/root/include/scc/bits/arm64/arch/stdlib.h b/root/include/scc/bits/arm64/arch/stdlib.h @@ -1,14 +0,0 @@ -#ifndef SIZET_ -typedef unsigned long size_t; -#define SIZET_ -#endif - -#define EXIT_FAILURE 1 -#define EXIT_SUCCESS 0 - -#ifndef _WCHAR_T -typedef int wchar_t; -#define _WCHAR_T -#endif - -#define _ALIGNTYPE long double diff --git a/root/include/scc/bits/arm64/arch/string.h b/root/include/scc/bits/arm64/arch/string.h @@ -1,6 +0,0 @@ -#ifndef SIZET_ -typedef unsigned long size_t; -#define SIZET_ -#endif - -#define __NUMCHARS 128 diff --git a/root/include/scc/bits/arm64/arch/time.h b/root/include/scc/bits/arm64/arch/time.h @@ -1,8 +0,0 @@ -#ifndef _SIZET -typedef unsigned long size_t; -#define _SIZET -#endif - -#define _MAXYEAR 9999 - -typedef long int time_t; diff --git a/root/include/scc/bits/dragonfly/sys.h b/root/include/scc/bits/dragonfly/sys.h @@ -1,19 +0,0 @@ -#define O_RDONLY 0x00000000 -#define O_WRONLY 0x00000001 -#define O_RDWR 0x00000002 - -#define O_TRUNC 0x00000400 -#define O_APPEND 0x00000008 -#define O_CREAT 0x00000200 - -typedef int pid_t; - -struct sigaction { - void (*sa_handler)(int); - char sa_mask[8]; - int sa_flags; -}; - -extern pid_t _getpid(void); -extern int _kill(pid_t pid, int signum); -extern int _sigaction(int sig, struct sigaction *new, struct sigaction *old); diff --git a/root/include/scc/bits/dragonfly/sys/signal.h b/root/include/scc/bits/dragonfly/sys/signal.h @@ -1,27 +0,0 @@ -typedef int sig_atomic_t; - -#define SIG_ERR ((void (*)(int))-1) -#define SIG_DFL ((void (*)(int)) 0) -#define SIG_IGN ((void (*)(int)) 1) - -#define SIGHUP 1 -#define SIGINT 2 -#define SIGQUIT 3 -#define SIGILL 4 -#define SIGABRT 6 -#define SIGFPE 8 -#define SIGKILL 9 -#define SIGSEGV 11 -#define SIGPIPE 13 -#define SIGALRM 14 -#define SIGTERM 15 -#define SIGSTOP 17 -#define SIGTSTP 18 -#define SIGCONT 19 -#define SIGCHLD 20 -#define SIGTTIN 21 -#define SIGTTOU 22 -#define SIGUSR1 30 -#define SIGUSR2 31 - -#define __NR_SIGNALS 32 diff --git a/root/include/scc/bits/i386/arch/limits.h b/root/include/scc/bits/i386/arch/limits.h @@ -1,18 +0,0 @@ -#define CHAR_BIT 8 -#define SCHAR_MAX 0x7F -#define SCHAR_MIN (-SCHAR_MIN-1) -#define CHAR_MAX 0x7F -#define CHAR_MIN (-CHAR_MAX-1) -#define UCHAR_MAX 0xFF -#define SHRT_MAX 0x7FFF -#define SHRT_MIN (-SHRT_MAX-1) -#define USHRT_MAX 0xFFFF -#define INT_MAX 0x7FFFFFFF -#define INT_MIN (-INT_MAX-1) -#define UINT_MAX 0xFFFFFFFF -#define LONG_MAX 0x7FFFFFFF -#define LONG_MIN (-LONG_MAX-1) -#define ULONG_MAX 0xFFFFFFFF -#define LLONG_MAX 0x7FFFFFFFFFFFFFFF -#define LLONG_MIN (-LLONG_MAX-1) -#define ULLONG_MAX 0xFFFFFFFFFFFFFFFF diff --git a/root/include/scc/bits/i386/arch/stddef.h b/root/include/scc/bits/i386/arch/stddef.h @@ -1,14 +0,0 @@ -#ifndef _SIZET -typedef unsigned long size_t; -#define _SIZET -#endif - -#ifndef _WCHAR_T -typedef int wchar_t; -#define _WCHAR_T -#endif - -#ifndef _PTRDIFF_T -typedef long ptrdiff_t; -#define _PTRDIFF_T -#endif diff --git a/root/include/scc/bits/i386/arch/stdint.h b/root/include/scc/bits/i386/arch/stdint.h @@ -1,115 +0,0 @@ -#define INT8_MAX 0x7F -#define INT8_MIN (-INT8_MAX-1) -#define UINT8_MAX 0xFF - -#define INT16_MAX 0x7FFF -#define INT16_MIN (-INT16_MAX-1) -#define UINT16_MAX 0xFFFF - -#define INT32_MAX 0x7FFFFFFF -#define INT32_MIN (-INT32_MAX-1) -#define UINT32_MAX 0xFFFFFFFF - -#define INT64_MAX 0x7FFFFFFFFFFFFFFF -#define INT64_MIN (-INT64_MAX-1) -#define UINT64_MAX 0xFFFFFFFFFFFFFFFF - -#define INT_LEAST8_MIN INT8_MIN -#define INT_LEAST8_MAX INT8_MAX -#define UINT_LEAST8_MAX UINT8_MAX - -#define INT_LEAST16_MIN INT16_MIN -#define INT_LEAST16_MAX INT16_MAX -#define UINT_LEAST16_MAX UINT16_MAX - -#define INT_LEAST32_MIN INT32_MIN -#define INT_LEAST32_MAX INT32_MAX -#define UINT_LEAST32_MAX UINT32_MAX - -#define INT_LEAST64_MIN INT64_MIN -#define INT_LEAST64_MAX INT64_MAX -#define UINT_LEAST64_MAX UINT64_MAX - -#define INT_FAST8_MIN INT32_MIN -#define INT_FAST8_MAX INT32_MAX -#define UINT_FAST8_MAX UINT32_MAX - -#define INT_FAST16_MIN INT32_MIN -#define INT_FAST16_MAX INT32_MAX -#define UINT_FAST16_MAX UINT32_MAX - -#define INT_FAST32_MIN INT32_MIN -#define INT_FAST32_MAX INT32_MAX -#define UINT_FAST32_MAX UINT32_MAX - -#define INT_FAST64_MIN INT64_MIN -#define INT_FAST64_MAX INT64_MAX -#define UINT_FAST64_MAX UINT64_MAX - -#define INTPTR_MIN INT32_MIN -#define INTPTR_MAX INT32_MAX -#define UINTPTR_MAX UINT32_MAX - -#define INTMAX_MIN INT64_MIN -#define INTMAX_MAX INT64_MAX -#define UINTMAX_MAX UINT64_MAX - -#define PTRDIFF_MIN INT32_MIN -#define PTRDIFF_MAX INT32_MAX - -#define SIG_ATOMIC_MIN INT32_MIN -#define SIG_ATOMIC_MAX INT32_MAX - -#define SIZE_MAX UINT32_MAX - -#define WCHAR_MIN INT32_MIN -#define WCHAR_MAX INT32_MAX - -#define INT8_C(x) x -#define INT16_C(x) x -#define INT32_C(x) x -#define INT64_C(x) x ## LL - -#define UINT8_C(x) x -#define UINT16_C(x) x -#define UINT32_C(x) x ## U -#define UINT64_C(x) x ## ULL - -#define INTMAX_C(x) x ## LL -#define UINTMAX_C(x) x ## ULL - -typedef signed char int8_t; -typedef short int16_t; -typedef int int32_t; -typedef long long int64_t; - -typedef unsigned char uint8_t; -typedef unsigned short uint16_t; -typedef unsigned uint32_t; -typedef unsigned long long uint64_t; - -typedef signed char int8_least_t; -typedef short int16_least_t; -typedef int int32_least_t; -typedef long long int64_least_t; - -typedef unsigned char uint8_least_t; -typedef unsigned short uint16_least_t; -typedef unsigned uint32_least_t; -typedef unsigned long long uint64_least_t; - -typedef int int8_fast_t; -typedef int int16_fast_t; -typedef int int32_fast_t; -typedef long long int64_fast_t; - -typedef unsigned uint8_fast_t; -typedef unsigned uint16_fast_t; -typedef unsigned uint32_fast_t; -typedef unsigned long long uint64_fast_t; - -typedef int intptr_t; -typedef unsigned uintptr_t; - -typedef long long intmax_t; -typedef unsigned long long uintmax_t; diff --git a/root/include/scc/bits/i386/arch/stdio.h b/root/include/scc/bits/i386/arch/stdio.h @@ -1,15 +0,0 @@ -#ifndef _SIZET -typedef unsigned long size_t; -#define _SIZET -#endif - -#define BUFSIZ 512 -#define FILENAME_MAX 256 -#define FOPEN_MAX 16 - -#define TMP_MAX 25 -#define L_tmpnam 256 - -#define _TMPNAME "/tmp/tmp.0000000" - -typedef long fpos_t; diff --git a/root/include/scc/bits/i386/arch/stdlib.h b/root/include/scc/bits/i386/arch/stdlib.h @@ -1,14 +0,0 @@ -#ifndef _SIZET -typedef unsigned long size_t; -#define _SIZET -#endif - -#define EXIT_FAILURE 1 -#define EXIT_SUCCESS 0 - -#ifndef _WCHAR_T -typedef int wchar_t; -#define _WCHAR_T -#endif - -#define _ALIGNTYPE long double diff --git a/root/include/scc/bits/i386/arch/string.h b/root/include/scc/bits/i386/arch/string.h @@ -1,5 +0,0 @@ -#ifndef _SIZET -typedef unsigned long size_t; -#endif - -#define __NUMCHARS 128 diff --git a/root/include/scc/bits/i386/arch/time.h b/root/include/scc/bits/i386/arch/time.h @@ -1,8 +0,0 @@ -#ifndef _SIZET -typedef unsigned long size_t; -#define _SIZET -#endif - -#define _MAXYEAR 2037 - -typedef long int time_t; diff --git a/root/include/scc/bits/linux/sys.h b/root/include/scc/bits/linux/sys.h @@ -1,19 +0,0 @@ -#define O_RDONLY 0x00000000 -#define O_WRONLY 0x00000001 -#define O_RDWR 0x00000002 - -#define O_TRUNC 0x00000400 -#define O_APPEND 0x00000008 -#define O_CREAT 0x00000200 - -typedef int pid_t; - -struct sigaction { - void (*sa_handler)(int); - int sa_mask; - int sa_flags; -}; - -extern pid_t _getpid(void); -extern int _kill(pid_t pid, int signum); -extern int _sigaction(int sig, struct sigaction *new, struct sigaction *old); diff --git a/root/include/scc/bits/linux/sys/signal.h b/root/include/scc/bits/linux/sys/signal.h @@ -1,27 +0,0 @@ -typedef int sig_atomic_t; - -#define SIG_ERR ((void (*)(int))-1) -#define SIG_DFL ((void (*)(int)) 0) -#define SIG_IGN ((void (*)(int)) 1) - -#define SIGHUP 1 -#define SIGINT 2 -#define SIGQUIT 3 -#define SIGILL 4 -#define SIGABRT 6 -#define SIGFPE 8 -#define SIGKILL 9 -#define SIGUSR1 10 -#define SIGSEGV 11 -#define SIGUSR2 12 -#define SIGPIPE 13 -#define SIGALRM 14 -#define SIGTERM 15 -#define SIGCHLD 17 -#define SIGCONT 18 -#define SIGSTOP 19 -#define SIGTSTP 20 -#define SIGTTIN 21 -#define SIGTTOU 22 - -#define __NR_SIGNALS 23 diff --git a/root/include/scc/bits/netbsd/sys.h b/root/include/scc/bits/netbsd/sys.h @@ -1,19 +0,0 @@ -#define O_RDONLY 0x00000000 -#define O_WRONLY 0x00000001 -#define O_RDWR 0x00000002 - -#define O_TRUNC 0x00000400 -#define O_APPEND 0x00000008 -#define O_CREAT 0x00000200 - -typedef int pid_t; - -struct sigaction { - void (*sa_handler)(int); - char sa_mask[8]; - int sa_flags; -}; - -extern pid_t _getpid(void); -extern int _kill(pid_t pid, int signum); -extern int _sigaction(int sig, struct sigaction *new, struct sigaction *old); diff --git a/root/include/scc/bits/netbsd/sys/signal.h b/root/include/scc/bits/netbsd/sys/signal.h @@ -1,27 +0,0 @@ -typedef int sig_atomic_t; - -#define SIG_ERR ((void (*)(int))-1) -#define SIG_DFL ((void (*)(int)) 0) -#define SIG_IGN ((void (*)(int)) 1) - -#define SIGHUP 1 -#define SIGINT 2 -#define SIGQUIT 3 -#define SIGILL 4 -#define SIGABRT 6 -#define SIGFPE 8 -#define SIGKILL 9 -#define SIGSEGV 11 -#define SIGPIPE 13 -#define SIGALRM 14 -#define SIGTERM 15 -#define SIGSTOP 17 -#define SIGTSTP 18 -#define SIGCONT 19 -#define SIGCHLD 20 -#define SIGTTIN 21 -#define SIGTTOU 22 -#define SIGUSR1 30 -#define SIGUSR2 31 - -#define __NR_SIGNALS 32 diff --git a/root/include/scc/bits/openbsd/sys.h b/root/include/scc/bits/openbsd/sys.h @@ -1,19 +0,0 @@ -#define O_RDONLY 0x00000000 -#define O_WRONLY 0x00000001 -#define O_RDWR 0x00000002 - -#define O_TRUNC 0x00000400 -#define O_APPEND 0x00000008 -#define O_CREAT 0x00000200 - -typedef int pid_t; - -struct sigaction { - void (*sa_handler)(int); - int sa_mask; - int sa_flags; -}; - -extern pid_t _getpid(void); -extern int _kill(pid_t pid, int signum); -extern int _sigaction(int sig, struct sigaction *new, struct sigaction *old); diff --git a/root/include/scc/bits/openbsd/sys/signal.h b/root/include/scc/bits/openbsd/sys/signal.h @@ -1,27 +0,0 @@ -typedef int sig_atomic_t; - -#define SIG_ERR ((void (*)(int))-1) -#define SIG_DFL ((void (*)(int)) 0) -#define SIG_IGN ((void (*)(int)) 1) - -#define SIGHUP 1 -#define SIGINT 2 -#define SIGQUIT 3 -#define SIGILL 4 -#define SIGABRT 6 -#define SIGFPE 8 -#define SIGKILL 9 -#define SIGSEGV 11 -#define SIGPIPE 13 -#define SIGALRM 14 -#define SIGTERM 15 -#define SIGSTOP 17 -#define SIGTSTP 18 -#define SIGCONT 19 -#define SIGCHLD 20 -#define SIGTTIN 21 -#define SIGTTOU 22 -#define SIGUSR1 30 -#define SIGUSR2 31 - -#define __NR_SIGNALS 32 diff --git a/root/include/scc/bits/z80/arch/limits.h b/root/include/scc/bits/z80/arch/limits.h @@ -1,18 +0,0 @@ -#define CHAR_BIT 8 -#define SCHAR_MAX 0x7F -#define SCHAR_MIN (-SCHAR_MIN-1) -#define CHAR_MAX 0xFF -#define CHAR_MIN 0 -#define UCHAR_MAX 0xFF -#define SHRT_MAX 0x7FFF -#define SHRT_MIN (-SHRT_MAX-1) -#define USHRT_MAX 0xFFFF -#define INT_MAX 0x7FFF -#define INT_MIN (-INT_MAX-1) -#define UINT_MAX 0xFFFF -#define LONG_MAX 0x7FFFFFFF -#define LONG_MIN (-LONG_MAX-1) -#define ULONG_MAX 0xFFFFFFFF -#define LLONG_MAX 0x7FFFFFFFFFFFFFFF -#define LLONG_MIN (-LLONG_MAX-1) -#define ULLONG_MAX 0xFFFFFFFFFFFFFFFF diff --git a/root/include/scc/bits/z80/arch/stddef.h b/root/include/scc/bits/z80/arch/stddef.h @@ -1,14 +0,0 @@ -#ifndef _SIZET -typedef unsigned size_t; -#define _SIZET -#endif - -#ifndef _WCHAR_T -typedef short wchar_t; -#define _WCHAR_T -#endif - -#ifndef _PTRDIFF_T -typedef short ptrdiff_t; -#define _PTRDIFF_T -#endif diff --git a/root/include/scc/bits/z80/arch/stdint.h b/root/include/scc/bits/z80/arch/stdint.h @@ -1,115 +0,0 @@ -#define INT8_MAX 0x7F -#define INT8_MIN (-INT8_MAX-1) -#define UINT8_MAX 0xFF - -#define INT16_MAX 0x7FFF -#define INT16_MIN (-INT16_MAX-1) -#define UINT16_MAX 0xFFFF - -#define INT32_MAX 0x7FFFFFFF -#define INT32_MIN (-INT32_MAX-1) -#define UINT32_MAX 0xFFFFFFFF - -#define INT64_MAX 0x7FFFFFFFFFFFFFFF -#define INT64_MIN (-INT64_MAX-1) -#define UINT64_MAX 0xFFFFFFFFFFFFFFFF - -#define INT_LEAST8_MIN INT8_MIN -#define INT_LEAST8_MAX INT8_MAX -#define UINT_LEAST8_MAX UINT8_MAX - -#define INT_LEAST16_MIN INT16_MIN -#define INT_LEAST16_MAX INT16_MAX -#define UINT_LEAST16_MAX UINT16_MAX - -#define INT_LEAST32_MIN INT32_MIN -#define INT_LEAST32_MAX INT32_MAX -#define UINT_LEAST32_MAX UINT32_MAX - -#define INT_LEAST64_MIN INT64_MIN -#define INT_LEAST64_MAX INT64_MAX -#define UINT_LEAST64_MAX UINT64_MAX - -#define INT_FAST8_MIN INT16_MIN -#define INT_FAST8_MAX INT16_MAX -#define UINT_FAST8_MAX UINT16_MAX - -#define INT_FAST16_MIN INT16_MIN -#define INT_FAST16_MAX INT16_MAX -#define UINT_FAST16_MAX UINT16_MAX - -#define INT_FAST32_MIN INT32_MIN -#define INT_FAST32_MAX INT32_MAX -#define UINT_FAST32_MAX UINT32_MAX - -#define INT_FAST64_MIN INT64_MIN -#define INT_FAST64_MAX INT64_MAX -#define UINT_FAST64_MAX UINT64_MAX - -#define INTPTR_MIN INT16_MIN -#define INTPTR_MAX INT16_MAX -#define UINTPTR_MAX UINT16_MAX - -#define INTMAX_MIN INT64_MIN -#define INTMAX_MAX INT64_MAX -#define UINTMAX_MAX UINT64_MAX - -#define PTRDIFF_MIN INT16_MIN -#define PTRDIFF_MAX INT16_MAX - -#define SIG_ATOMIC_MIN INT16_MIN -#define SIG_ATOMIC_MAX INT16_MAX - -#define SIZE_MAX UINT64_MAX - -#define WCHAR_MIN INT16_MIN -#define WCHAR_MAX INT16_MAX - -#define INT8_C(x) x -#define INT16_C(x) x -#define INT32_C(x) x ## L -#define INT64_C(x) x ## LL - -#define UINT8_C(x) x -#define UINT16_C(x) x ## U -#define UINT32_C(x) x ## UL -#define UINT64_C(x) x ## ULL - -#define INTMAX_C(x) x ## LL -#define UINTMAX_C(x) x ## ULL - -typedef signed char int8_t; -typedef int int16_t; -typedef long int32_t; -typedef long long int64_t; - -typedef unsigned char uint8_t; -typedef unsigned uint16_t; -typedef unsigned long uint32_t; -typedef unsigned long long uint64_t; - -typedef signed char int8_least_t; -typedef int int16_least_t; -typedef long int32_least_t; -typedef long long int64_least_t; - -typedef unsigned char uint8_least_t; -typedef unsigned uint16_least_t; -typedef unsigned long uint32_least_t; -typedef unsigned long long uint64_least_t; - -typedef signed char int8_fast_t; -typedef int int16_fast_t; -typedef long int32_fast_t; -typedef long long int64_fast_t; - -typedef unsigned char uint8_fast_t; -typedef unsigned uint16_fast_t; -typedef unsigned long uint32_fast_t; -typedef unsigned long long uint64_fast_t; - -typedef int intptr_t; -typedef unsigned uintptr_t; - -typedef long long intmax_t; -typedef unsigned long long uintmax_t; diff --git a/root/include/scc/bits/z80/arch/stdio.h b/root/include/scc/bits/z80/arch/stdio.h @@ -1,15 +0,0 @@ -#ifndef _SIZET -typedef unsigned size_t; -#define _SIZET -#endif - -#define BUFSIZ 512 -#define FILENAME_MAX 256 -#define FOPEN_MAX 16 - -#define TMP_MAX 25 -#define L_tmpnam 256 - -#define _TMPNAME "TMP.000" - -typedef long fpos_t; diff --git a/root/include/scc/bits/z80/arch/stdlib.h b/root/include/scc/bits/z80/arch/stdlib.h @@ -1,14 +0,0 @@ -#ifndef _SIZET -typedef unsigned size_t; -#define _SIZET -#endif - -#define EXIT_FAILURE 1 -#define EXIT_SUCCESS 0 - -#ifndef _WCHAR_T -typedef short wchar_t; -#define _WCHAR_T -#endif - -#define _ALIGNTYPE int diff --git a/root/include/scc/bits/z80/arch/string.h b/root/include/scc/bits/z80/arch/string.h @@ -1,5 +0,0 @@ -#ifndef _SIZET -typedef unsigned size_t; -#endif - -#define __NUMCHARS 128 diff --git a/root/include/scc/bits/z80/arch/time.h b/root/include/scc/bits/z80/arch/time.h @@ -1,8 +0,0 @@ -#ifndef _SIZET -typedef unsigned size_t; -#define _SIZET -#endif - -#define _MAXYEAR 2037 - -typedef long time_t; diff --git a/root/include/scc/ctype.h b/root/include/scc/ctype.h @@ -1,45 +0,0 @@ -#ifndef _CTYPE_H -#define _CTYPE_H - -extern int isalnum(int c); -extern int isalpha(int c); -extern int islower(int c); -extern int isupper(int c); -extern int isdigit(int c); -extern int isxdigit(int c); -extern int iscntrl(int c); -extern int isgraph(int c); -extern int isspace(int c); -extern int isblank(int c); -extern int isprint(int c); -extern int ispunct(int c); -extern int tolower(int c); -extern int toupper(int c); - - -#define _U 0x01 /* upper */ -#define _L 0x02 /* lower */ -#define _D 0x04 /* digit */ -#define _C 0x08 /* cntrl */ -#define _P 0x10 /* punct */ -#define _S 0x20 /* white space (space/lf/tab) */ -#define _X 0x40 /* hex char */ -#define _SP 0x80 /* hard space (0x20) */ - -extern const unsigned char __ctype[]; - -#define isalnum(c) ((__ctype+1)[c] & (_U|_L|_D)) -#define isalpha(c) ((__ctype+1)[c] & (_U|_L)) -#define iscntrl(c) ((__ctype+1)[c] & (_C)) -#define isdigit(c) ((__ctype+1)[c] & (_D)) -#define isgraph(c) ((__ctype+1)[c] & (_P|_U|_L|_D)) -#define islower(c) ((__ctype+1)[c] & (_L)) -#define isprint(c) ((__ctype+1)[c] & (_P|_U|_L|_D|_SP)) -#define ispunct(c) ((__ctype+1)[c] & (_P)) -#define isspace(c) ((__ctype+1)[c] & (_S)) -#define isupper(c) ((__ctype+1)[c] & (_U)) -#define isxdigit(c) ((__ctype+1)[c] & (_D|_X)) - -#define isascii(c) ((unsigned)(c)<=0x7f) - -#endif diff --git a/root/include/scc/errno.h b/root/include/scc/errno.h @@ -1,6 +0,0 @@ -#ifndef _ERRNO_H -#define _ERRNO_H - -#include <sys/errno.h> - -#endif diff --git a/root/include/scc/float.h b/root/include/scc/float.h @@ -1 +0,0 @@ -/* TODO: Placeholder for compatibility with libraries that need to include it */ diff --git a/root/include/scc/limits.h b/root/include/scc/limits.h @@ -1,8 +0,0 @@ -#ifndef _LIMITS_H -#define _LIMITS_H - -#include <arch/limits.h> - -#define MB_LEN_MAX 1 - -#endif diff --git a/root/include/scc/locale.h b/root/include/scc/locale.h @@ -1,39 +0,0 @@ -#ifndef _LOCALE_H -#define _LOCALE_H - -#ifndef NULL -#define NULL ((void *) 0) -#endif - -#define LC_ALL 0 -#define LC_COLLATE 1 -#define LC_CTYPE 2 -#define LC_MONETARY 3 -#define LC_NUMERIC 4 -#define LC_TIME 5 - -struct lconv { - char *decimal_point; - char *thousands_sep; - char *grouping; - char *mon_decimal_point; - char *mon_thousands_sep; - char *mon_grouping; - char *positive_sign; - char *negative_sign; - char *currency_symbol; - char *int_curr_symbol; - char frac_digits; - char p_cs_precedes; - char n_cs_precedes; - char p_sep_by_space; - char n_sep_by_space; - char p_sign_posn; - char n_sign_posn; - char int_frac_digits; -}; - -extern char *setlocale(int category, const char *locale); -extern struct lconv *localeconv(void); - -#endif diff --git a/root/include/scc/math.h b/root/include/scc/math.h @@ -1,4 +0,0 @@ -#ifndef _MATH_H -#define _MATH_H -#error math.h is not supported yet -#endif diff --git a/root/include/scc/setjmp.h b/root/include/scc/setjmp.h @@ -1,11 +0,0 @@ -#ifndef _SETJMP_H -#define _SETJMP_H - -#include <arch/setjmp.h> - -extern int setjmp(jmp_buf env); -extern void longjmp(jmp_buf env, int val); - -#define setjmp setjmp - -#endif diff --git a/root/include/scc/signal.h b/root/include/scc/signal.h @@ -1,9 +0,0 @@ -#ifndef _SIGNAL_H -#define _SIGNAL_H - -#include <sys/signal.h> - -void ( *signal(int signum, void (*handler)(int)) ) (int); -int raise(int sig); - -#endif diff --git a/root/include/scc/stdarg.h b/root/include/scc/stdarg.h @@ -1,10 +0,0 @@ -#ifndef _STDARG_H -#define _STDARG_H - -typedef __builtin_va_list va_list; -#define va_start(ap, last) __builtin_va_start(ap, last) -#define va_end(ap) __builtin_va_end(ap) -#define va_copy(to, from) __builtin_va_copy(to, from) -#define va_arg(to, type) __builtin_va_arg(to, type) - -#endif diff --git a/root/include/scc/stdbool.h b/root/include/scc/stdbool.h @@ -1,9 +0,0 @@ -#ifndef _STDBOOL_H -#define _STDBOOL_H - -#define bool _Bool -#define true 1 -#define false 0 -#define __bool_true_false_are_defined 1 - -#endif diff --git a/root/include/scc/stddef.h b/root/include/scc/stddef.h @@ -1,12 +0,0 @@ -#ifndef _STDDEF_H -#define _STDDEF_H - -#include <arch/stddef.h> - -#ifndef NULL -#define NULL ((void *) 0) -#endif - -#define offsetof(st, m) ((size_t)&(((st *)0)->m)) - -#endif diff --git a/root/include/scc/stdint.h b/root/include/scc/stdint.h @@ -1,6 +0,0 @@ -#ifndef _STDINT_H_ -#define _STDINT_H_ - -#include <arch/stdint.h> - -#endif diff --git a/root/include/scc/stdio.h b/root/include/scc/stdio.h @@ -1,123 +0,0 @@ -#ifndef _STDIO_H -#define _STDIO_H - -#include <arch/stdio.h> - -#ifndef FOPEN_MAX -#define FOPEN_MAX 12 -#endif - -#ifndef NULL -#define NULL ((void *) 0) -#endif - -#define EOF -1 -#define SEEK_CUR 0 -#define SEEK_END 1 -#define SEEK_SET 2 - - -#define _IOWRITE (1 << 0) -#define _IOREAD (1 << 1) -#define _IORW (1 << 2) -#define _IOEOF (1 << 3) -#define _IOERR (1 << 4) -#define _IOSTRG (1 << 5) -#define _IOTXT (1 << 6) -#define _IOFBF (1 << 7) -#define _IOLBF (1 << 8) -#define _IONBF (1 << 9) -#define _IOALLOC (1 <<10) - -typedef struct { - int fd; /* file descriptor */ - unsigned char *buf; /* pointer to i/o buffer */ - unsigned char *rp; /* read pointer */ - unsigned char *wp; /* write pointer */ - unsigned char *lp; /* write pointer used when line-buffering */ - size_t len; /* actual length of buffer */ - unsigned short flags; - unsigned char unbuf[1]; /* tiny buffer for unbuffered io */ -} FILE; - -extern FILE __iob[FOPEN_MAX]; - -#define stdin (&__iob[0]) -#define stdout (&__iob[1]) -#define stderr (&__iob[2]) - -extern int remove(const char *filename); -extern int rename(const char *old, const char *new); -extern FILE *tmpfile(void); -extern char *tmpnam(char *s); -extern int fclose(FILE *fp); -extern int fflush(FILE *fp); -extern FILE *fopen(const char * restrict fname, const char * restrict mode); -extern FILE *freopen(const char * restrict fname, const char * restrict mode, - FILE * restrict fp); -extern void setbuf(FILE * restrict fp, char * restrict buf); -extern int setvbuf(FILE * restrict fp, - char * restrict buf, int mode, size_t size); -extern int fprintf(FILE * restrict fp, const char * restrict fmt, ...); -extern int fscanf(FILE * restrict fp, const char * restrict fmt, ...); -extern int printf(const char * restrict fmt, ...); -extern int scanf(const char * restrict fmt, ...); -extern int snprintf(char * restrict s, - size_t n, const char * restrict fmt, ...); -extern int sprintf(char * restrict s, const char * restrict fmt, ...); -extern int sscanf(const char * restrict s, const char * restrict fmt, ...); - -#ifdef _STDARG_H -extern int vfprintf(FILE * restrict fp, - const char * restrict fmt, va_list arg); -extern int vfscanf(FILE * restrict fp, - const char * restrict fmt, va_list arg); -extern int vprintf(const char * restrict fmt, va_list arg); -extern int vscanf(const char * restrict fmt, va_list arg); -extern int vsnprintf(char * restrict s, size_t n, const char * restrict fmt, - va_list arg); -extern int vsprintf(char * restrict s, - const char * restrict fmt, va_list arg); -extern int vsscanf(const char * restrict s, - const char * restrict fmt, va_list arg); -#endif - -extern int fgetc(FILE *fp); -extern char *fgets(char * restrict s, int n, FILE * restrict fp); -extern int fputc(int c, FILE *fp); -extern int fputs(const char * restrict s, FILE * restrict fp); -extern int getc(FILE *fp); -extern int getchar(void); -extern char *gets(char *s); -extern int putc(int c, FILE *fp); -extern int putchar(int c); -extern int puts(const char *s); -extern int ungetc(int c, FILE *fp); -extern size_t fread(void * restrict ptr, size_t size, size_t nmemb, - FILE * restrict fp); -extern size_t fwrite(const void * restrict ptr, size_t size, size_t nmemb, - FILE * restrict fp); -extern int fgetpos(FILE * restrict fp, fpos_t * restrict pos); -extern int fseek(FILE *fp, long int offset, int whence); -extern int fsetpos(FILE *fp, const fpos_t *pos); -extern long int ftell(FILE *fp); -extern void rewind(FILE *fp); -extern void clearerr(FILE *fp); -extern int feof(FILE *fp); -extern int ferror(FILE *fp); -extern void perror(const char *s); - -extern int __getc(FILE *fp); -extern int __putc(int, FILE *fp); - -#define getc(fp) ((fp)->rp >= (fp)->wp ? __getc(fp) : *(fp)->rp++) -#define putc(c, fp) ((fp)->wp >= (fp)->rp ? __putc(c,fp) : (*(fp)->wp++ = c)) - -#define ferror(fp) ((fp)->flags & _IOERR) -#define feof(fp) ((fp)->flags & _IOEOF) -#define clearerr(fp) (void) ((fp)->flags &= ~(_IOERR|_IOEOF)) -#define getchar() getc(stdin) -#define putchar(c) putc((c), stdout) -#define setbuf(fp, b) (void) setvbuf(fp, b, b ? _IOFBF:_IONBF, BUFSIZ) - -#endif diff --git a/root/include/scc/stdlib.h b/root/include/scc/stdlib.h @@ -1,69 +0,0 @@ -#ifndef _STDLIB_H -#define _STDLIB_H - -#include <arch/stdlib.h> - -#ifndef NULL -#define NULL ((void *) 0) -#endif - -#define _ATEXIT_MAX 32 - -#define MB_CUR_MAX 1 -#define RAND_MAX 32767 - -typedef struct { - int quot, rem; -} div_t; - -typedef struct { - long quot, rem; -} ldiv_t; - -typedef struct { - long long quot, rem; -} lldiv_t; - -extern double atof(const char *nptr); -extern int atoi(const char *nptr); -extern long int atol(const char *nptr); -extern long long int atoll(const char *nptr); -extern double strtod(const char * restrict nptr, char ** restrict endptr); -extern float strtof(const char * restrict nptr, char ** restrict endptr); -extern long double strtold(const char * restrict nptr, char ** restrict endptr); -extern long int strtol(const char * restrict nptr, char ** restrict endptr, int base); -extern long long int strtoll(const char * restrict nptr, char ** restrict endptr, - int base); -extern unsigned long int strtoul(const char * restrict nptr, char ** restrict endptr, - int base); -extern unsigned long long int strtoull(const char * restrict nptr, - char ** restrict endptr, int base); -extern int rand(void); -extern void srand(unsigned int seed); -extern void *calloc(size_t nmemb, size_t size); -extern void free(void *ptr); -extern void *malloc(size_t size); -extern void *realloc(void *ptr, size_t size); -extern void abort(void); -extern int atexit(void (*func)(void)); -extern void exit(int status); -extern void _Exit(int status); -extern char *getenv(const char *name); -extern int system(const char *string); -extern void *bsearch(const void *key, const void *base, size_t nmemb, size_t size, - int (*compar)(const void *, const void *)); -extern void qsort(void *base, size_t nmemb, size_t size, - int (*compar)(const void *, const void *)); -extern int abs(int j); -extern long int labs(long int j); -extern long long int llabs(long long int j); -extern div_t div(int numer, int denom); -extern ldiv_t ldiv(long int numer, long int denom); -extern lldiv_t lldiv(long long int numer, long long int denom); -extern int mblen(const char *s, size_t n); -extern int mbtowc(wchar_t * restrict pwc, const char * restrict s, size_t n); -extern int wctomb(char *s, wchar_t wchar); -extern size_t mbstowcs(wchar_t * restrict pwcs, const char * restrict s, size_t n); -extern size_t wcstombs(char * restrict s, const wchar_t * restrict pwcs, size_t n); - -#endif diff --git a/root/include/scc/string.h b/root/include/scc/string.h @@ -1,34 +0,0 @@ -#ifndef _STRING_H -#define _STRING_H - -#include <arch/string.h> - -#ifndef NULL -#define NULL ((void *) 0) -#endif - -extern void *memcpy(void * restrict s1, const void * restrict s2, size_t n); -extern void *memmove(void *s1, const void *s2, size_t n); -extern char *strcpy(char * restrict s1, const char * restrict s2); -extern char *strncpy(char * restrict s1, const char * restrict s2, size_t n); -extern char *strcat(char * restrict s1, const char * restrict s2); -extern char *strncat(char * restrict s1, const char * restrict s2, size_t n); -extern int memcmp(const void *s1, const void *s2, size_t n); -extern int strcmp(const char *s1, const char *s2); -extern int strcoll(const char *s1, const char *s2); -extern int strncmp(const char *s1, const char *s2, size_t n); -extern size_t strxfrm(char * restrict s1, const char * restrict s2, size_t n); -extern void *memchr(const void *s, int c, size_t n); -extern char *strchr(const char *s, int c); -extern size_t strcspn(const char *s1, const char *s2); -extern char *strpbrk(const char *s1, const char *s2); -extern char *strrchr(const char *s, int c); -extern size_t strspn(const char *s1, const char *s2); -extern char *strstr(const char *s1, const char *s2); -extern char *strtok(char * restrict s1, const char * restrict s2); -extern void *memset(void *s, int c, size_t n); -extern char *strerror(int errnum); -extern size_t strlen(const char *s); -extern size_t strnlen(const char *s, size_t maxlen); - -#endif diff --git a/root/include/scc/time.h b/root/include/scc/time.h @@ -1,43 +0,0 @@ -#ifndef _TIME_H -#define _TIME_H - -#include <arch/time.h> - -#ifndef NULL -#define NULL ((void *) 0) -#endif - -#define CLOCKS_PER_SEC 1000000 - -typedef long int clock_t; - -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; - - /* fields used internally */ - - char *tm_zone; - long tm_gmtoff; -}; - -extern clock_t clock(void); -extern double difftime(time_t time1, time_t time0); -extern time_t mktime(struct tm *timeptr); -extern time_t time(time_t *timer); -extern char *asctime(const struct tm *timeptr); -extern char *ctime(const time_t *timer); -extern struct tm *gmtime(const time_t *timer); -extern struct tm *localtime(const time_t *timer); -extern size_t strftime(char * restrict s, size_t maxsize, - const char * restrict format, - const struct tm * restrict timeptr); - -#endif diff --git a/root/include/scc/wchar.h b/root/include/scc/wchar.h @@ -1,92 +0,0 @@ -#ifndef _WCHAR_H -#define _WCHAR_H - -/* TODO: This is only a placeholder */ -typedef long wchar_t; -/* typedef long size_t; */ -typedef long mbstate_t; -typedef long wint_t; -struct tm; - -/* #define WCHAR_MAX 1 */ -/* #define WCHAR_MIN 1 */ -/* #define WEOF -1 */ -/* #define NULL 0 */ - -#ifdef _STDARG_H -extern int vswscanf(const wchar_t * restrict s, const wchar_t * restrict format, va_list arg); -extern int vwprintf(const wchar_t * restrict format, va_list arg); -extern int vwscanf(const wchar_t * restrict format, va_list arg); -#endif - -#ifdef _STDIO_H -extern int fwprintf(FILE * restrict stream, const wchar_t * restrict format, ...); -extern int fwscanf(FILE * restrict stream, const wchar_t * restrict format, ...); - -#ifdef _STDARG_H -extern int vfwprintf(FILE * restrict stream, const wchar_t * restrict format, va_list arg); -extern int vfwscanf(FILE * restrict stream, const wchar_t * restrict format, va_list arg); -extern int vswprintf(wchar_t * restrict s, size_t n, const wchar_t * restrict format, va_list arg); -#endif - -extern wint_t fgetwc(FILE *stream); -extern wint_t fputwc(wchar_t c, FILE *stream); -extern wint_t getwc(FILE *stream); -extern wint_t putwc(wchar_t c, FILE *stream); -extern int fwide(FILE *stream, int mode); -extern wint_t ungetwc(wint_t c, FILE *stream); -extern wchar_t *fgetws(wchar_t * restrict s, int n, FILE * restrict stream); -extern int fputws(const wchar_t * restrict s, FILE * restrict stream); -#endif - -extern int swprintf(wchar_t * restrict s, size_t n, const wchar_t * restrict format, ...); -extern int swscanf(const wchar_t * restrict s, const wchar_t * restrict format, ...); -extern int wprintf(const wchar_t * restrict format, ...); -extern int wscanf(const wchar_t * restrict format, ...); - -extern wint_t getwchar(void); -extern wint_t putwchar(wchar_t c); - -extern double wcstod(const wchar_t * restrict nptr, wchar_t ** restrict endptr); -extern float wcstof(const wchar_t * restrict nptr, wchar_t ** restrict endptr); -extern long double wcstold(const wchar_t * restrict nptr, wchar_t ** restrict endptr); - -extern long int wcstol(const wchar_t * restrict nptr, wchar_t ** restrict endptr, int base); -extern long long int wcstoll(const wchar_t * restrict nptr, wchar_t ** restrict endptr, int base); -extern unsigned long int wcstoul(const wchar_t * restrict nptr, wchar_t ** restrict endptr, int base); -extern unsigned long long int wcstoull(const wchar_t * restrict nptr, wchar_t ** restrict endptr, int base); - -extern wchar_t *wcscpy(wchar_t * restrict s1, const wchar_t * restrict s2); -extern wchar_t *wcsncpy(wchar_t * restrict s1, const wchar_t * restrict s2, size_t n); - -extern wchar_t *wmemcpy(wchar_t * restrict s1, const wchar_t * restrict s2, size_t n); -extern wchar_t *wmemmove(wchar_t *s1, const wchar_t *s2, size_t n); -extern wchar_t *wcscat(wchar_t * restrict s1, const wchar_t * restrict s2); -extern wchar_t *wcsncat(wchar_t * restrict s1, const wchar_t * restrict s2, size_t n); -extern int wcscmp(const wchar_t *s1, const wchar_t *s2); -extern int wcscoll(const wchar_t *s1, const wchar_t *s2); -extern int wcsncmp(const wchar_t *s1, const wchar_t *s2, size_t n); -extern size_t wcsxfrm(wchar_t * restrict s1, const wchar_t * restrict s2, size_t n); -extern int wmemcmp(const wchar_t *s1, const wchar_t *s2, size_t n); -extern wchar_t *wcschr(const wchar_t *s, wchar_t c); -extern size_t wcscspn(const wchar_t *s1, const wchar_t *s2); -extern wchar_t *wcspbrk(const wchar_t *s1, const wchar_t *s2); -extern wchar_t *wcsrchr(const wchar_t *s, wchar_t c); -extern size_t wcsspn(const wchar_t *s1, const wchar_t *s2); -extern wchar_t *wcsstr(const wchar_t *s1, const wchar_t *s2); -extern wchar_t *wcstok(wchar_t * restrict s1, const wchar_t * restrict s2, wchar_t ** restrict ptr); -extern wchar_t *wmemchr(const wchar_t *s, wchar_t c, size_t n); -extern size_t wcslen(const wchar_t *s); -extern wchar_t *wmemset(wchar_t *s, wchar_t c, size_t n); -extern size_t wcsftime(wchar_t * restrict s, size_t maxsize, const wchar_t * restrict format, const struct tm * restrict timeptr); -extern wint_t btowc(int c); -extern int wctob(wint_t c); -extern int mbsinit(const mbstate_t *ps); -extern size_t mbrlen(const char * restrict s, size_t n, mbstate_t * restrict ps); -extern size_t mbrtowc(wchar_t * restrict pwc, const char * restrict s, size_t n, mbstate_t * restrict ps); -extern size_t wcrtomb(char * restrict s, wchar_t wc, mbstate_t * restrict ps); -extern size_t mbsrtowcs(wchar_t * restrict dst, const char ** restrict src, size_t len, mbstate_t * restrict ps); -extern size_t wcsrtombs(char * restrict dst, const wchar_t ** restrict src, size_t len, mbstate_t * restrict ps); - - -#endif diff --git a/root/include/scc/wctype.h b/root/include/scc/wctype.h @@ -1,30 +0,0 @@ -#ifndef _WCTYPE_H -#define _WCTYPE_H - -/* TODO: This is only a placeholder */ -typedef int wint_t; -typedef int wctrans_t; -typedef int wctype_t; - -#define WEOF -1 - -extern int iswalnum(wint_t wc); -extern int iswalpha(wint_t wc); -extern int iswblank(wint_t wc); -extern int iswcntrl(wint_t wc); -extern int iswdigit(wint_t wc); -extern int iswgraph(wint_t wc); -extern int iswlower(wint_t wc); -extern int iswprint(wint_t wc); -extern int iswpunct(wint_t wc); -extern int iswspace(wint_t wc); -extern int iswupper(wint_t wc); -extern int iswxdigit(wint_t wc); -extern int iswctype(wint_t wc, wctype_t desc); -extern wctype_t wctype(const char *property); -extern wint_t towlower(wint_t wc); -extern wint_t towupper(wint_t wc); -extern wint_t towctrans(wint_t wc, wctrans_t desc); -extern wctrans_t wctrans(const char *property); - -#endif diff --git a/root/lib/scc/amd64-sysv-linux/README b/root/lib/scc/amd64-sysv-linux/README @@ -1 +0,0 @@ -This is a placeholder for VCS diff --git a/root/lib/scc/amd64-sysv-netbsd/README b/root/lib/scc/amd64-sysv-netbsd/README @@ -1 +0,0 @@ -This is a placeholder for VCS diff --git a/root/lib/scc/amd64-sysv-openbsd/README b/root/lib/scc/amd64-sysv-openbsd/README @@ -1 +0,0 @@ -This is a placeholder for VCS diff --git a/root/lib/scc/i386-sysv-linux/README b/root/lib/scc/i386-sysv-linux/README @@ -1 +0,0 @@ -This is a placeholder for VCS diff --git a/root/lib/scc/i386-sysv-openbsd/README b/root/lib/scc/i386-sysv-openbsd/README @@ -1 +0,0 @@ -This is a placeholder for VCS diff --git a/root/lib/scc/z80-scc-none/README b/root/lib/scc/z80-scc-none/README @@ -1 +0,0 @@ -This is a placeholder for VCS diff --git a/root/libexec/scc/README b/root/libexec/scc/README @@ -1 +0,0 @@ -This is a placeholder for VCS diff --git a/rules.mk b/rules.mk @@ -1,37 +0,0 @@ -include $(PROJECTDIR)/config.mk - -INCLUDE = $(PROJECTDIR)/inc - -BINDIR = $(PROJECTDIR)/root/bin -INCDIR = $(PROJECTDIR)/root/include/scc -LIBDIR = $(PROJECTDIR)/root/lib/scc -LIBEXEC = $(PROJECTDIR)/root/libexec/scc - -LIBSCC = $(PROJECTDIR)/lib/scc -LIBCOFF32 = $(PROJECTDIR)/lib/coff32 - -SCC_CFLAGS = $(MORECFLAGS) $(SYSCFLAGS) $(STDCFLAGS) -g $(CFLAGS) - -SCC_LDFLAGS = $(MORELFLAGS) $(SYSLDFLAGS) -L$(LIBDIR) -g $(LDFLAGS) - -# helper macro to run over all the directories -FORALL = +@set -e ;\ - pwd=$$PWD; \ - for i in $(DIRS); \ - do \ - cd $$i; \ - $(MAKE) $@; \ - cd $$pwd; \ - done - -.s.o: - $(AS) $< -o $@ - -.c.o: - $(CC) $(SCC_CFLAGS) -o $@ -c $< - -all: -dep: -clean: -distclean: clean -FORCE: diff --git a/scripts/libc-proto b/scripts/libc-proto @@ -0,0 +1,10 @@ +bin +include/scc +libexec/scc +lib +lib/scc +lib/scc/i386-linux +lib/scc/amd64-netbsd +lib/scc/amd64-linux +lib/scc/amd64-openbsd +lib/scc/i386-openbsd diff --git a/scripts/mkdep b/scripts/mkdep @@ -0,0 +1,22 @@ +#!/bin/sh + +set -e + +(echo '/^#deps/+;$c' + +for i in `find . -name '*.c'` +do + file=`basename $i | sed 's/\.c$/.o/'` + + dir=`dirname $i | + sed -e 's,^\./,,' -e 's,^\.$,,' -e 's,...*[^/],&/,'` + + sed -n "/^#include / { + s/// + s@\"\(.*\)\"@$dir$file: $dir\1@p + s@<\(scc/.*\)>@$dir$file: \$(INCDIR)/scc/\1@p + }" $i +done | LC_ALL=C sort -s + +echo . +echo w) | ed -s deps.mk diff --git a/scripts/rules.mk b/scripts/rules.mk @@ -0,0 +1,52 @@ +CONF=amd64-linux +include $(PROJECTDIR)/config/$(CONF).mk + +LIBDIR = $(PROJECTDIR)/lib/scc +SCRIPTDIR = $(PROJECTDIR)/scripts +INCDIR = $(PROJECTDIR)/include + +BINDIR = $(PROJECTDIR)/bin +LIBEXEC = $(PROJECTDIR)/libexec/scc +CRTDIR = $(PROJECTDIR)/lib/scc + +SCC_CFLAGS = $(MORECFLAGS) \ + $(SYSCFLAGS) \ + -I$(INCDIR)/scc \ + -g \ + $(CFLAGS) + +SCC_LDFLAGS = $(MORELFLAGS) \ + $(SYSLDFLAGS) \ + -L$(LIBDIR) \ + -g \ + $(LDFLAGS) + +# helper macro to run over all the directories +FORALL = +@set -e ;\ + pwd=$$PWD; \ + for i in $(DIRS); \ + do \ + cd $$i; \ + $(MAKE) $@; \ + cd $$pwd; \ + done + +.s.o: + $(AS) $< -o $@ + +.c.o: + $(CC) $(SCC_CFLAGS) -o $@ -c $< + +all: + +dep: + +inc-dep: FORCE + $(SCRIPTDIR)/mkdep + +clean: clean-helper + +clean-helper: + rm -f *.o $(OBJS) $(TARGET) + +FORCE: diff --git a/src/Makefile b/src/Makefile @@ -0,0 +1,20 @@ +.POSIX: + +PROJECTDIR = .. +include $(PROJECTDIR)/scripts/rules.mk + +TOOLS = cc1 cc2 ld as nm objdump +LIBS = libscc libcoff32 +DIRS = $(TOOLS) $(LIBS) libc libcrt + +all: $(TOOLS) crt + +crt: libcrt libc $(TOOLS) + +$(TOOLS): $(LIBS) + +$(DIRS): FORCE + +@cd $@ && $(MAKE) + +dep clean: + $(FORALL) diff --git a/src/ar/Makefile b/src/ar/Makefile @@ -0,0 +1,22 @@ +.POSIX: + +PROJECTDIR = ../.. +include $(PROJECTDIR)/scripts/rules.mk + +MORECFLAGS = -I$(DRIVER) + +OBJS = main.o \ + $(DRIVER)/driver.o \ + +TARGET = $(BINDIR)/ar + +all: $(TARGET) + +$(TARGET): $(LIBDIR)/libscc.a + +$(TARGET): $(OBJS) + $(CC) $(SCC_LDFLAGS) $(OBJS) -lscc -o $@ + +dep: inc-dep + +include deps.mk diff --git a/src/ar/deps.mk b/src/ar/deps.mk @@ -0,0 +1,5 @@ +#deps +main.o: $(INCDIR)/scc/ar.h +main.o: $(INCDIR)/scc/arg.h +main.o: $(INCDIR)/scc/scc.h +posix/driver.o: posix/driver.h diff --git a/src/ar/main.c b/src/ar/main.c @@ -0,0 +1,643 @@ +static char sccsid[] = "@(#) ./ar/main.c"; + +#include <errno.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> + +#include <driver.h> + +#include <scc/ar.h> +#include <scc/arg.h> +#include <scc/scc.h> + +enum { + BEFORE, + INDOT, + AFTER, +}; + +struct tmp { + char *name; + FILE *fp; +} tmps[3]; + +char *argv0; + +static int bflag, vflag, cflag, lflag, uflag, aflag; +static char *arfile, *posname; + +struct member { + FILE *src; + struct ar_hdr hdr; + int cur; + char *fname; + long size; + long mode; + long long date; +}; + +static void +cleanup(void) +{ + int i; + + for (i = 0; i < 3; i++) { + if (tmps[i].name) + remove(tmps[i].name); + } +} + +/* + * I do know that you cannot call remove from a signal handler + * but we only can use stdio function to deal with files + * because we are C99 compliant, and it is very likely that + * remove is going to work in this case + */ +static void +sigfun(int signum) +{ + cleanup(); + _Exit(1); +} + +static FILE * +openar(void) +{ + FILE *fp; + char magic[SARMAG+1]; + + if ((fp = fopen(arfile,"r+b")) == NULL) { + if (!cflag) + fprintf(stderr, "ar: creating %s\n", arfile); + if ((fp = fopen(arfile, "w+b")) == NULL) { + perror("ar:opening archive"); + exit(1); + } + fputs(ARMAG, fp); + if (fflush(fp) == EOF) { + perror("ar:writing magic number"); + exit(1); + } + } else { + if (fgets(magic, sizeof(magic), fp) == NULL) { + perror("ar:error reading magic number"); + exit(1); + } + if (strcmp(magic, ARMAG)) { + fprintf(stderr, + "ar:%s:invalid magic number '%s'\n", + arfile, + magic); + exit(1); + } + } + return fp; +} + +static void +archive(char *fname, FILE *to, char letter) +{ + int c; + size_t n; + FILE *from; + char mtime[13]; + struct stat st; + + if (vflag) + printf("%c - %s\n", letter, fname); + if (strlen(fname) > 16) + fprintf(stderr, "ar:%s: too long name\n", fname); + if ((from = fopen(fname, "rb")) == NULL) { + fprintf(stderr, + "ar:opening member '%s':%s\n", + fname, + strerror(errno)); + exit(1); + } + if (stat(fname, &st) < 0) { + fprintf(stderr, "ar:error getting '%s' attributes\n", fname); + exit(1); + } + strftime(mtime, sizeof(mtime), "%s", gmtime(&st.st_mtime)); + fprintf(to, + "%-16.16s%-12s%-6u%-6u%-8o%-10llu`\n", + fname, + mtime, + st.st_uid, + st.st_gid, + st.st_mode, + (unsigned long long) st.st_size); + for (n = 0; (c = getc(from)) != EOF; n++) + putc(c, to); + if (n & 1) + putc('\n', to); + if (ferror(from)) { + fprintf(stderr, + "ar:reading input '%s':%s\n", + fname, strerror(errno)); + exit(1); + } + fclose(from); +} + +static void +append(FILE *fp, char *argv[]) +{ + char *fname; + + if (fseek(fp, 0, SEEK_END) == EOF) { + perror("ar:seeking archive"); + exit(1); + } + + for ( ; fname = *argv; ++argv) { + *argv = NULL; + archive(fname, fp, 'a'); + } + + if (fclose(fp) == EOF) { + perror("ar:error writing archive"); + exit(1); + } +} + +static void +copy(struct member *m, struct tmp *tmp) +{ + int c; + size_t siz = m->size; + struct ar_hdr *hdr = &m->hdr; + + fwrite(hdr, sizeof(*hdr), 1, tmp->fp); + if ((siz & 1) == 1) + siz++; + while (siz--) { + if ((c = getc(m->src)) == EOF) + break; + fputc(c, tmp->fp); + } +} + +static void +letters(unsigned long val, char *s) +{ + *s++ = (val & 04) ? 'r' : '-'; + *s++ = (val & 02) ? 'w' : '-'; + *s++ = (val & 01) ? 'x' : '-'; +} + +static char * +perms(struct member *m) +{ + static char buf[10]; + + letters(m->mode >> 6, buf); + letters(m->mode >> 3, buf+3); + letters(m->mode, buf +6); + buf[9] = '\0'; + + return buf; +} + +static int +inlist(char *fname, int argc, char *argv[]) +{ + for (; argc-- > 0; ++argv) { + if (*argv && !strcmp(*argv, fname)) { + *argv = NULL; + return 1; + } + } + return 0; +} + +static void +move(struct member *m, int argc, char *argv[]) +{ + int where; + + if (inlist(m->fname, argc, argv)) { + if (vflag) + printf("m - %s\n", m->fname); + where = INDOT; + } else if (posname && !strcmp(posname, m->fname)) { + where = (bflag) ? AFTER : BEFORE; + m->cur = AFTER; + } else { + where = m->cur; + } + copy(m, &tmps[where]); +} + +static void +insert(int argc, char *argv[]) +{ + for (; argc-- > 0; ++argv) { + if (*argv) { + archive(*argv, tmps[INDOT].fp, 'a'); + *argv = NULL; + } + } +} + +static void +update(struct member *m, int argc, char *argv[]) +{ + int where; + FILE *fp = tmps[BEFORE].fp; + + if (inlist(m->fname, argc, argv)) { + archive(m->fname, tmps[m->cur].fp, 'r'); + return; + } else if (posname && !strcmp(posname, m->fname)) { + where = (bflag) ? AFTER : BEFORE; + m->cur = AFTER; + } else { + where = m->cur; + } + copy(m, &tmps[where]); +} + +static void +extract(struct member *m, int argc, char *argv[]) +{ + int c; + long siz; + FILE *fp; + + if (argc > 0 && !inlist(m->fname, argc, argv)) + return; + if (vflag) + printf("x - %s\n", m->fname); + siz = m->size; + + if ((fp = fopen(m->fname, "wb")) == NULL) + goto error_file; + while (siz-- > 0 && (c = getc(m->src)) != EOF) + putc(c, fp); + fflush(fp); + if (fclose(fp) == EOF) + goto error_file; + + /* TODO: set attributes */ + return; + + +error_file: + perror("ar:error extracting file"); + exit(1); +} + +static void +print(struct member *m, int argc, char *argv[]) +{ + long siz; + int c; + + if (argc > 0 && !inlist(m->fname, argc, argv)) + return; + if (vflag) + printf("\n<%s>\n\n", m->fname); + siz = m->size; + while (siz-- > 0 && (c = getc(m->src)) != EOF) + putchar(c); +} + +static void +list(struct member *m, int argc, char *argv[]) +{ + time_t t; + struct ar_hdr *hdr = &m->hdr; + char mtime[30]; + + if (argc > 0 && !inlist(m->fname, argc, argv)) + return; + if (!vflag) { + printf("%s\n", m->fname); + } else { + t = totime(m->date); + strftime(mtime, sizeof(mtime), "%c", localtime(&t)); + printf("%s %ld/%ld\t%s %s\n", + perms(m), + atol(hdr->ar_uid), + atol(hdr->ar_gid), + mtime, + m->fname); + } +} + +static void +del(struct member *m, int argc, char *argv[]) +{ + if (inlist(m->fname, argc, argv)) { + if (vflag) + printf("d - %s\n", m->fname); + return; + } + copy(m, &tmps[BEFORE]); +} + +static char * +getfname(struct ar_hdr *hdr) +{ + static char fname[SARNAM+1]; + size_t i; + + memcpy(fname, hdr->ar_name, SARNAM); + fname[SARNAM] = '\0'; + + for (i = SARNAM-1; i >= 0; --i) { + if (fname[i] != ' ' && fname[i] != '/') + break; + fname[i] = '\0'; + } + return fname; +} + +static long long +getnum(char *s, int size, int base) +{ + int c; + long long val; + char *p; + static char digits[] = "0123456789"; + + for (val = 0; size > 0; val += c) { + --size; + if ((c = *s++) == ' ') + break; + if ((p = strchr(digits, c)) == NULL) + return -1; + if ((c = p - digits) >= base) + return -1; + val *= base; + } + + while (size > 0 && *s++ == ' ') + --size; + return (size == 0) ? val : -1; +} + +static int +valid(struct member *m) +{ + struct ar_hdr *hdr = &m->hdr; + + m->fname = getfname(&m->hdr); + m->size = getnum(hdr->ar_size, sizeof(hdr->ar_size), 10); + m->mode = getnum(hdr->ar_mode, sizeof(hdr->ar_mode), 8); + m->date = getnum(hdr->ar_date, sizeof(hdr->ar_date), 10); + + if (strncmp(hdr->ar_fmag, ARFMAG, sizeof(hdr->ar_fmag)) || + m->size < 0 || m->mode < 0 || m->date < 0) { + return 0; + } + return 1; +} + +static void +run(FILE *fp, int argc, char *argv[], + void (*fun)(struct member *, int argc, char *files[])) +{ + struct member m; + + m.src = fp; + m.cur = BEFORE; + + while (fread(&m.hdr, sizeof(m.hdr), 1, fp) == 1) { + fpos_t pos; + + if (!valid(&m)) { + fprintf(stderr, + "ar:corrupted member '%s'\n", + m.fname); + exit(1); + } + fgetpos(fp, &pos); + (*fun)(&m, argc, argv); + fsetpos(fp, &pos); + fseek(fp, m.size+1 & ~1, SEEK_CUR); + } + if (ferror(fp) || fclose(fp) == EOF) { + perror("ar:reading members"); + exit(1); + } +} + +static void +merge(void) +{ + FILE *fp, *fi; + int c, i; + + + if ((fp = fopen(arfile, "wb")) == NULL) { + perror("ar:reopening archive"); + exit(1); + } + + fputs(ARMAG, fp); + + for (i = 0; i < 3; i++) { + if ((fi = tmps[i].fp) == NULL) + continue; + fseek(fi, 0, SEEK_SET); + while ((c = getc(fi)) != EOF) + putc(c, fp); + if (ferror(fi)) { + perror("ar:error in temporary"); + exit(1); + } + } + + if (fclose(fp) == EOF) { + perror("ar:writing archive file"); + exit(1); + } +} + +static void +closetmp(int which) +{ + struct tmp *tmp = &tmps[which]; + + if (!tmp->fp) + return; + if (fclose(tmp->fp) == EOF) { + perror("ar:closing temporaries"); + exit(1); + } +} + +static void +opentmp(char *fname, int which) +{ + struct tmp *tmp = &tmps[which]; + + if (lflag) { + tmp->name = fname; + tmp->fp = fopen(fname, "w+b"); + } else { + tmp->fp = tmpfile(); + } + + if (tmp->fp == NULL) { + perror("ar:creating temporary"); + exit(1); + } +} + +static void +doit(int key, char *argv[], int argc) +{ + FILE *fp; + + fp = openar(); + if (argc == 0 && + (key == 'r' || key == 'd' || key == 'm' || key == 'q')) { + if (fclose(fp) == EOF) { + perror("ar:early close of archive file"); + exit(-1); + } + return; + } + + if (key == 'r' || key == 'm' || key == 'd') + opentmp("ar.tmp1", BEFORE); + if (key == 'r' || key == 'm') { + opentmp("ar.tmp2", INDOT); + opentmp("ar.tmp3", AFTER); + } + + switch (key) { + case 'r': + run(fp, argc, argv, update); + insert(argc, argv); + merge(); + break; + case 'm': + run(fp, argc, argv, move); + merge(); + break; + case 'd': + run(fp, argc, argv, del); + merge(); + break; + case 't': + run(fp, argc, argv, list); + break; + case 'p': + run(fp, argc, argv, print); + break; + case 'x': + run(fp, argc, argv, extract); + break; + case 'q': + append(fp, argv); + break; + } + + closetmp(BEFORE); + closetmp(INDOT); + closetmp(AFTER); + + for ( ; argc-- > 0; ++argv) { + if (*argv) { + fprintf(stderr, "ar: No member named '%s'\n", *argv); + exit(1); + } + } +} + +static void +usage(void) +{ + fputs("ar [-drqtpmx][posname] [-vuaibcl] [posname] arfile name ...\n", + stderr); + exit(1); +} + +int +main(int argc, char *argv[]) +{ + int key, nkey = 0, pos = 0; + + atexit(cleanup); + ARGBEGIN { + case 'd': + nkey++; + key = 'd'; + break; + case 'r': + nkey++; + key = 'r'; + break; + case 'q': + nkey++; + key = 'q'; + break; + case 't': + nkey++; + key = 't'; + break; + case 'p': + nkey++; + key = 'p'; + break; + case 'm': + nkey++; + key = 'm'; + break; + case 'x': + nkey++; + key = 'x'; + break; + case 'a': + aflag = 1; + pos++; + posname = EARGF(usage()); + break; + case 'i': + case 'b': + bflag = 1; + pos++; + posname = EARGF(usage()); + break; + case 'v': + vflag = 1; + break; + case 'c': + cflag = 1; + break; + case 'l': + lflag = 1; + break; + case 'u': + /* TODO */ + abort(); + uflag = 1; + break; + default: + usage(); + } ARGEND + + if (nkey == 0 || nkey > 1 || pos > 1 || argc == 0) + usage(); + + signal(SIGINT, sigfun); + signal(SIGQUIT, sigfun); + signal(SIGTERM, sigfun); + + arfile = *argv; + doit(key, ++argv, --argc); + + if (fflush(stdout) == EOF) { + perror("ar:error writing to stdout"); + exit(1); + } + + return 0; +} diff --git a/ar/posix/driver.c b/src/ar/posix/driver.c diff --git a/ar/posix/driver.h b/src/ar/posix/driver.h diff --git a/src/as/Makefile b/src/as/Makefile @@ -0,0 +1,33 @@ +.POSIX: + +PROJECTDIR = ../.. +include $(PROJECTDIR)/scripts/rules.mk + +MORECFLAGS = -I$(INCDIR)/$(STD) + +OBJS = main.o \ + symbol.o \ + ins.o \ + parser.o \ + expr.o \ + myro.o \ + +TARGET = $(LIBEXEC)/as-amd64 \ + $(LIBEXEC)/as-i386 \ + $(LIBEXEC)/as-i286 \ + $(LIBEXEC)/as-z80 \ + +all: $(TARGET) + +$(TARGET): $(LIBDIR)/libscc.a + +dep: inc-dep + +clean: + rm -f target/*/*.o target/*/*tbl.c + +include target/amd64.mk +include target/i386.mk +include target/i286.mk +include target/z80.mk +include deps.mk diff --git a/as/as.h b/src/as/as.h diff --git a/src/as/deps.mk b/src/as/deps.mk @@ -0,0 +1,33 @@ +#deps +expr.o: $(INCDIR)/scc/scc/scc.h +expr.o: as.h +ins.o: $(INCDIR)/scc/scc/scc.h +ins.o: as.h +main.o: $(INCDIR)/scc/scc/arg.h +main.o: $(INCDIR)/scc/scc/scc.h +main.o: as.h +myro.o: $(INCDIR)/scc/scc/myro.h +myro.o: $(INCDIR)/scc/scc/scc.h +myro.o: as.h +parser.o: $(INCDIR)/scc/scc/cstd.h +parser.o: $(INCDIR)/scc/scc/scc.h +parser.o: as.h +symbol.o: $(INCDIR)/scc/scc/scc.h +symbol.o: as.h +target/x80/ins.o: $(INCDIR)/scc/scc/scc.h +target/x80/ins.o: target/x80/../../as.h +target/x80/ins.o: target/x80/proc.h +target/x80/z80.o: $(INCDIR)/scc/scc/scc.h +target/x80/z80.o: target/x80/../../as.h +target/x80/z80.o: target/x80/../x80/proc.h +target/x86/amd64.o: $(INCDIR)/scc/scc/scc.h +target/x86/amd64.o: target/x86/../../as.h +target/x86/i286.o: $(INCDIR)/scc/scc/scc.h +target/x86/i286.o: target/x86/../../as.h +target/x86/i286.o: target/x86/../x86/proc.h +target/x86/i386.o: $(INCDIR)/scc/scc/scc.h +target/x86/i386.o: target/x86/../../as.h +target/x86/i386.o: target/x86/../x86/proc.h +target/x86/ins.o: $(INCDIR)/scc/scc/scc.h +target/x86/ins.o: target/x86/../../as.h +target/x86/ins.o: target/x86/proc.h diff --git a/src/as/expr.c b/src/as/expr.c @@ -0,0 +1,303 @@ +static char sccsid[] = "@(#) ./as/expr.c"; + +#include <ctype.h> +#include <stdlib.h> +#include <string.h> + +#include <scc/scc.h> +#include "as.h" + +#define NNODES 10 + +static Alloc *arena; + +Node * +node(int op, Node *l, Node *r) +{ + struct arena *ap; + Node *np; + + if (!arena) + arena = alloc(sizeof(Node), NNODES); + np = new(arena); + np->op = op; + np->left = l; + np->right = r; + np->sym = NULL; + + return np; +} + +void +deltree(Node *np) +{ + if (!np) + return; + deltree(np->left); + deltree(np->right); + delete(arena, np); +} + +static Node * +fold(int op, Node *l, Node *r) +{ + Node *np; + TUINT val, lv, rv; + + lv = l->sym->value; + rv = r->sym->value; + + /* TODO: check overflow */ + + switch (op) { + case '*': + val = lv - rv; + break; + case '/': + if (rv == 0) + goto division_by_zero; + val = lv / rv; + break; + case '%': + if (rv == 0) + goto division_by_zero; + val = lv % rv; + break; + case SHL: + val = lv << rv; + break; + case SHR: + val = lv >> rv; + break; + case '+': + val = lv + rv; + break; + case '-': + val = lv - rv; + break; + case '<': + val = lv < rv; + break; + case '>': + val = lv > rv; + break; + case '=': + val = lv == rv; + break; + case GE: + val = lv >= rv; + break; + case LE: + val = lv <= rv; + break; + case '|': + val = lv | rv; + break; + case '^': + val = lv ^ rv; + break; + default: + abort(); + } + deltree(l); + deltree(r); + + np = node(NUMBER, NULL, NULL); + np->sym = tmpsym(val); + np->addr = ANUMBER; + return np; + +division_by_zero: + error("division by 0"); +} + +static Node * +binary(int op, Node *l, Node *r) +{ + int addr; + Node *np; + + if (l->op == NUMBER && r->op == NUMBER) + return fold(op, l, r); + else + abort(); + np = node(op, l, r); + np->addr = addr; + + return np; +} + +static Node * +unaryop(int op, Node *np) +{ + TUINT val; + + if (np->addr != ANUMBER) + error("invalid argument for unary operator"); + if (np->op != NUMBER) { + np = node(op, np, NULL); + np->addr = ANUMBER; + return np; + } + + val = np->sym->value; + switch (op) { + case '!': + val = !val; + case '+': + break; + case '-': + val = -val; + break; + default: + abort(); + } + np->sym->value = val; + + return np; +} + +/*************************************************************************/ +/* grammar functions */ +/*************************************************************************/ + +static Node * +primary(void) +{ + Node *np; + + switch (yytoken) { + case IDEN: + case NUMBER: + np = node(yytoken, NULL, NULL); + np->sym = yylval.sym; + np->addr = ANUMBER; + next(); + break; + case '(': + np = expr(); + expect(')'); + break; + default: + unexpected(); + } + + return np; +} + +static Node * +unary(void) +{ + int op, tok; + Node *np; + + switch (tok = yytoken) { + case '!': + case '-': + case '+': + next(); + return unaryop(tok, primary()); + default: + return primary(); + } +} + +static Node * +mul(void) +{ + int op; + Node *np; + + np = unary(); + for (;;) { + switch (op = yytoken) { + case '*': + case '/': + case '%': + case SHL: + case SHR: + next(); + binary(op, np, primary()); + break; + default: + return np; + } + } +} + +static Node * +add(void) +{ + int op; + Node *np; + + np = mul(); + for (;;) { + switch (op = yytoken) { + case '+': + case '-': + next(); + np = binary(op, np, mul()); + break; + default: + return np; + } + } +} + +static Node * +relational(void) +{ + int op; + Node *np; + + np = add(); + for (;;) { + switch (op = yytoken) { + case '<': + case '>': + case '=': + case GE: + case LE: + next(); + np = binary(op, np, add()); + break; + default: + return np; + } + } +} + +static Node * +and(void) +{ + int op; + Node *np; + + np = relational(); + while (accept('&')) + np = binary('&', np, relational()); + return np; +} + +Node * +expr(void) +{ + int op; + Node *np; + + regctx(0); + np = and(); + for (;;) { + switch (op = yytoken) { + case '|': + case '^': + next(); + np = binary(op, np, and()); + break; + default: + regctx(1); + return np; + } + } +} diff --git a/src/as/ins.c b/src/as/ins.c @@ -0,0 +1,249 @@ +static char sccsid[] = "@(#) ./as/ins.c"; + +#include <string.h> + +#include <scc/scc.h> +#include "as.h" + +extern Section *sabs, *sbss, *sdata, *stext; + +enum { + EQU, + COMMON, + SIZE, + XSTRING, + ASCII, + TYPE, +}; + +char * +tobytes(TUINT v, int nbytes, int inc) +{ + static char buf[sizeof(TUINT)]; + int idx; + + idx = (inc < 0) ? nbytes-1 : 0; + while (nbytes--) { + buf[idx] = v; + idx += inc; + v >>= 8; + } + + if (v) + error("overflow in immediate value"); + return buf; +} + +void +noargs(Op *op, Node **args) +{ + emit(op->bytes, op->size); +} + +static void +xstring(int which, Node **args) +{ + Node *np; + char *s; + size_t len; + + while (np = *args++) { + s = np->sym->name.buf; + len = strlen(s); + len += which == XSTRING; + emit(s, len); + } +} + +void +string(Op *op, Node **args) +{ + xstring(STRING, args); +} + +void +ascii(Op *op, Node **args) +{ + xstring(STRING, args); +} + +void +def(Node **args, int siz) +{ + Node *np; + + while (np = *args++) { + Symbol *sym = np->sym; + + if ((sym->flags & FABS) == 0) + reloc(sym, 0, siz, siz * 8, 0); + emit(tobytes(sym->value, siz, endian), siz); + } +} + +void +defb(Op *op, Node **args) +{ + def(args, 1); +} + +void +defw(Op *op, Node **args) +{ + def(args, 2); +} + +void +defd(Op *op, Node **args) +{ + def(args, 4); +} + +void +defq(Op *op, Node **args) +{ + def(args, 8); +} + +static void +symexp(int which, Op *op, Node **args) +{ + Symbol *sym, *exp; + static char *cmds[] = { + [EQU] = "equ", + [COMMON] = "common", + [SIZE] = "size", + }; + char *cmd = cmds[which]; + + if (args[1]) { + sym = args[0]->sym; + exp = args[1]->sym; + } else if (linesym) { + sym = linesym; + exp = args[0]->sym; + } else { + error("%s pseudo instruction lacks a label", cmd); + } + + if ((exp->flags & FABS) == 0) + error("%s expression is not an absolute expression", cmd); + + switch (which) { + case EQU: + if (pass == 1 && (sym->flags & FDEF)) + error("redefinition of symbol '%s'", sym->name.buf); + sym->value = exp->value; + sym->flags |= FDEF; + break; + case COMMON: + sym->flags |= FCOMMON; + case SIZE: + sym->size = exp->value; + break; + case TYPE: + sym->type.buf = xstrdup(exp->name.buf); + break; + } +} + +void +equ(Op *op, Node **args) +{ + symexp(EQU, op, args); +} + +void +common(Op *op, Node **args) +{ + symexp(COMMON, op, args); +} + +void +size(Op *op, Node **args) +{ + symexp(SIZE, op, args); +} + +void +type(Op *op, Node **args) +{ + symexp(TYPE, op, args); +} + +void +section(Op *op, Node **args) +{ + Symbol *sym = args[0]->sym; + char *attr = NULL; + + if (args[1]) + attr = args[1]->sym->name.buf; + + setsec(sym->name.buf, attr); +} + +void +text(Op *op, Node **args) +{ + cursec = stext; +} + +void +data(Op *op, Node **args) +{ + cursec = sdata; +} + +void +bss(Op *op, Node **args) +{ + cursec = sbss; +} + +void +extrn(Op *op, Node **args) +{ + Symbol *sym = args[0]->sym; + + sym->flags |= FEXTERN; +} + +void +global(Op *op, Node **args) +{ + Symbol *sym = args[0]->sym; + + sym->flags |= FGLOBAL; +} + +void +align(Op *op, Node **args) +{ + Symbol *sym = args[0]->sym; + TUINT curpc, pc, al; + + if ((sym->flags & FABS) == 0) + error("align expression is not an absolute expression"); + if ((al = sym->value) == 0) + return; + + al--; + curpc = cursec->curpc; + pc = curpc+al & ~al; + + for (al = pc - curpc; al > 0; --al) + emit((char []) {0}, 1); +} + +void +end(Op *op, Node **args) +{ + endpass = 1; +} + +void +include(Op *op, Node **args) +{ + addinput(args[0]->sym->name.buf); +} diff --git a/src/as/main.c b/src/as/main.c @@ -0,0 +1,138 @@ +static char sccsid[] = "@(#) ./as/main.c"; + +#include <ctype.h> +#include <setjmp.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <scc/scc.h> +#include <scc/arg.h> +#include "as.h" + +char *argv0; +char *outfile, *infile; +int endpass; + + +static void +cleanup(void) +{ + if (outfile) + remove(outfile); +} + +static int +cmp(const void *f1, const void *f2) +{ + const Ins *ins = f2; + const char *s = f1; + int d; + + if ((d = *s - *ins->str) != 0) + return d; + + return strcmp(s, ins->str); +} + +static void +as(char *text, char *xargs) +{ + int c; + char *p; + Ins *ins; + Op *op, *lim; + Node **args; + + for (p = text; c = *p; ++p) + *p = toupper(c); + + ins = bsearch(text, instab, nr_ins, sizeof(Ins), cmp); + if (!ins) { + error("invalid instruction '%s'", text); + return; + } + + args = getargs(xargs); + lim = &optab[ins->end]; + for (op = &optab[ins->begin]; op < lim; ++op) { + if (match(op, args)) + break; + } + if (op == lim) { + error("invalid operands for '%s'", text); + return; + } + (*op->format)(op, args); +} + +static int +dopass(char *fname) +{ + struct line line; + FILE *fp; + extern int nerrors; + extern jmp_buf recover; + + addinput(fname); + cleansecs(); + + endpass = 0; + setjmp(recover); + while (!endpass && nextline(fp, &line)) { + linesym = NULL; + + if (line.label) + linesym = deflabel(line.label); + + if (line.op) + as(line.op, line.args); + else if (line.args) + error("arguments without an opcode"); + } + + return nerrors == 0; +} + +static void +usage(void) +{ + fputs("usage: as [-o outfile] filename ...\n", stderr); + exit(1); +} + +int +main(int argc, char *argv[]) +{ + char **p; + + outfile = "a.out"; + + ARGBEGIN { + case 'o': + outfile = EARGF(usage()); + break; + default: + usage(); + } ARGEND + + if (argc == 0) + usage(); + + atexit(cleanup); + iarch(); + isecs(); + + for (pass = 1; pass <= 2; pass++) { + for (p = argv; infile = *p; ++p) { + if (!dopass(infile)) + return 1; + } + if (pass == 1) + killtmp(); + } + writeout(outfile); + outfile = NULL; + + return 0; +} diff --git a/src/as/mktbl b/src/as/mktbl @@ -0,0 +1,32 @@ +#!/bin/sh + + +set -e + +for i +do + case $i in + -c) + cpu=$2 + shift 2 + ;; + -f) + family=$2 + shift 2 + ;; + -*) + echo mktbl: incorrect parameter:$i >&2 + exit 1 + ;; + esac +done + +echo cpu=${cpu:=z80} family=${family:=x80} + +rm -f $$.c target/$family/${cpu}tbl.c +trap "rm -f $$.c" 0 2 3 + +awk '!/^$/ {print $1,NR,$2,$3,$4,$5,$6}' target/$family/$family.dat | +LC_COLLATE=C sort -k1 -k2n | +awk -v cpu=`echo $cpu | tr a-z A-Z` -v family=$family -f mktbl.awk > $$.c && +mv $$.c target/$family/${cpu}tbl.c diff --git a/src/as/mktbl.awk b/src/as/mktbl.awk @@ -0,0 +1,112 @@ + +BEGIN { + printf "#include <scc/scc.h>\n"\ + "#include \"../../as.h\"\n"\ + "#include \"../" family "/proc.h\"\n" + + rules = "target/" family "/rules.dat" + while (getline < rules > 0) { + regex[++nregs] = $1 + value[nregs] = $2 + } + close(rules) +} + {sub(/#.*/,"")} + +$7 !~ cpu {next} + +/^$/ {next} + + { + if (opstart[$1] == 0) { + opstart[$1] = nvar + opnames[nop++] = $1 + } + opcount[$1]++ + opargs[nvar] = $3 + opsize[nvar] = $4 + opbytes[nvar] = ($5 == "none") ? "" : $5 + opformat[nvar++] = $6 + formats[$6] = 1 +} + +END { + for (i in formats) + printf "Format %s;\n", i + + printf "int nr_ins = %d;\n\n", nop + print "struct ins instab[] = {" + for (i = 0; i < nop; i++) { + n = opnames[i] + start = opstart[n] + end = start + opcount[n] + printf "\t{.str = \"%s\", .begin = %d, .end = %d},\n", + n, start, end | "sort" + } + close("sort") + printf "};\n\n" + + print "struct op optab[] = {" + for (i = 0; i < nvar; i++) { + printf "\t/* %d */\n", i + printf "\t{\n" \ + "\t\t.size = %d,\n"\ + "\t\t.format = %s,\n", + opsize[i], opformat[i] + + if (opbytes[i] != "") + printf "\t\t.bytes = (unsigned char [%d]) {%s},\n", + opsize[i], + opbytes[i] + + a = str2args(opargs[i]) + if (a != "") + printf "\t\t.args = (unsigned char []) {%s}\n", a + + print "\t}," + } + print "};" +} + +function str2args(s, args, i, j, out, n, found) +{ + n = split(s, args, /,/) + if (n == 0 || args[1] == "none") + return "" + for (i = 1; i <= n; i++) { + a = args[i] + found = 0 + + if (a ~ /\?$/) + out = out "AOPT ," + else if (a ~ /\+$/) + out = out "AREP ," + + for (j = 1; j <= nregs; j++) { + if (match(a, "^" regex[j])) { + out = out value[j] + found = 1 + break + } + } + + if (!found) { + print FILENAME ":" NR ":" \ + $0 ":wrong arg", a > "/dev/stderr" + exit 1 + } + + a = substr(a, RLENGTH+1) + sub(/\?$/, "", a) + sub(/\+$/, "", a) + if (a != "") { + print FILENAME ":" NR ":" \ + $0 ": trailing chars: ", a > "/dev/stderr" + exit 1 + } + out = out "," + } + out = out "0" + + return out +} diff --git a/src/as/myro.c b/src/as/myro.c @@ -0,0 +1,204 @@ +static char sccsid[] = "@(#) ./as/myro.c"; + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <scc/scc.h> +#include <scc/myro.h> +#include "as.h" + +#define FORMAT "z80-scc" + +static Reloc *relocs; +static size_t relcap, relsiz; + +static size_t +writestrings(FILE *fp) +{ + int type; + size_t off = 0; + size_t len; + Symbol *sym; + Section *sp; + String *str; + + fwrite(FORMAT, sizeof(FORMAT), 1, fp); + off = sizeof(FORMAT); + + for (sym = symlist; sym; sym = sym->next) { + if (sym->flags & FREG) + continue; + str = &sym->name; + len = strlen(str->buf) + 1; + fwrite(str->buf, len, 1, fp); + str->offset = off; + off += len; + } + + return off; +} + +static unsigned +getsecflags(Section *sp) +{ + unsigned flags = 0; + + if (sp->flags & SREAD) + flags |= MYROSEC_READ; + if (sp->flags & SWRITE) + flags |= MYROSEC_WRITE; + if (sp->flags & SFILE) + flags |= MYROSEC_FILE; + if (sp->flags & SEXEC) + flags |= MYROSEC_EXEC; + if (sp->flags & SLOAD) + flags |= MYROSEC_LOAD; + if (sp->flags & SABS) + flags |= MYROSEC_ABS; + return flags; +} + +static size_t +writesections(FILE *fp) +{ + Section *sp; + size_t off = 0; + struct myrosect sect; + unsigned id = 0;; + + for (sp = seclist; sp; sp = sp->next) { + if (id == MYROMAXSEC) + die("too many sections for a myro file"); + sp->id = id++; + sect.name = sp->sym->name.offset; + sect.flags = getsecflags(sp); + sect.fill = sp->fill; + sect.aligment = sp->aligment; + sect.offset = off; + sect.len = sp->max - sp->base; + off += wrmyrosec(fp, &sect); + } + + return off; +} + +static unsigned +getsymflags(Symbol *sym) +{ + unsigned flags = 0; + + if (sym->flags & FCOMMON) + flags |= MYROSYM_COMMON; + if (sym->flags & FEXTERN) + flags |= MYROSYM_EXTERN; + if (!(sym->flags & FDEF)) + flags |= MYROSYM_UNDEF; + return flags; +} + +static size_t +writesymbols(FILE *fp) +{ + Symbol *sym; + size_t off = 0; + struct myrosym symbol; + + for (sym = symlist; sym; sym = sym->next) { + if (sym->flags & (FREG|FSECT)) + continue; + symbol.name = sym->name.offset; + symbol.type = -1; + symbol.section = sym->section->id; + symbol.flags = getsymflags(sym); + symbol.offset = sym->value; + symbol.len = sym->size; + off += wrmyrosym(fp, &symbol); + } + + return off; +} + +static size_t +writerelocs(FILE *fp) +{ + Reloc *bp, *lim; + size_t off = 0; + struct myrorel reloc; + + lim = &relocs[relsiz]; + for (bp = relocs; bp < lim; ++bp) { + reloc.id = 0; + reloc.flags = bp->flags; + reloc.size = bp->size; + reloc.nbits = bp->nbits; + reloc.shift = bp->shift; + reloc.offset = bp->offset; + off += wrmyrorel(fp, &reloc); + } + return off; +} + +static void +writedata(FILE *fp) +{ + Section *sp; + + for (sp = seclist; sp; sp = sp->next) { + if (!sp->mem) + continue; + fwrite(sp->mem, sp->max - sp->base, 1, fp); + } +} + +void +writeout(char *name) +{ + FILE *fp; + struct myrohdr hdr = { .magic = MYROMAGIC }; + + if ((fp = fopen(name, "wb")) == NULL) + die("error opening output file '%s'\n", name); + + wrmyrohdr(fp, &hdr); + hdr.strsize = writestrings(fp); + hdr.secsize = writesections(fp); + hdr.symsize = writesymbols(fp); + hdr.relsize = writerelocs(fp); + writedata(fp); + + fseek(fp, 0, SEEK_SET); + wrmyrohdr(fp, &hdr); + + if (fclose(fp)) + die("error writing the output file"); +} + +void +reloc(Symbol *sym, + unsigned flags, unsigned size, unsigned nbits, unsigned shift) +{ + size_t tmp; + Reloc *p; + + if (pass == 1) + return; + + if (relcap == relsiz) { + tmp = ((relcap + 1) * 3) / 2; + if ((p = realloc(relocs, tmp * sizeof(Reloc))) == NULL) { + tmp = relcap + 1; + p = xrealloc(relocs, tmp * sizeof(Reloc)); + } + relcap = tmp; + relocs = p; + } + + p = &relocs[relsiz++]; + p->sym = sym; + p->flags = flags; + p->size = size; + p->nbits = nbits; + p->shift = shift; + p->offset = cursec->pc - cursec->base; +} diff --git a/src/as/parser.c b/src/as/parser.c @@ -0,0 +1,482 @@ +static char sccsid[] = "@(#) ./as/parser.c"; +#include <assert.h> +#include <ctype.h> +#include <errno.h> +#include <limits.h> +#include <setjmp.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <scc/cstd.h> +#include <scc/scc.h> +#include "as.h" + +#define NARGS 20 +#define NR_INPUTS 10 +#define MAXLINE 100 + +struct input { + char *fname; + unsigned lineno; + FILE *fp; +}; + +int nerrors; +jmp_buf recover; +char yytext[INTIDENTSIZ+1]; +int yytoken; +size_t yylen; +union yylval yylval; + +static char *textp, *endp; +static int regmode; +static unsigned lineno; +static struct input inputs[NR_INPUTS], *isp = inputs; + +static int +follow(int expect1, int expect2, int ifyes1, int ifyes2, int ifno) +{ + int c; + + if ((c = *++textp) == expect1) + return ifyes1; + if (c == expect2) + return ifyes2; + --textp; + return ifno; +} + +static void +tok2str(void) +{ + if ((yylen = endp - textp) > INTIDENTSIZ) { + error("token too big"); + yylen = INTIDENTSIZ; + } + memcpy(yytext, textp, yylen); + yytext[yylen] = '\0'; + textp = endp; +} + +static int +iden(void) +{ + int c; + char *p; + + for ( ; c = *endp; ++endp) { + if (isalnum(c)) + continue; + switch (c) { + case '\'': + case '_': + case '-': + case '.': + case '$': + continue; + default: + goto out_loop; + } + } + +out_loop: + tok2str(); + yylval.sym = lookup(yytext); + + return (yylval.sym->flags & FREG) ? REG : IDEN; +} + +static int +number(void) +{ + int c, base = 10; + char *p; + TUINT n; + + if (*endp == '0') { + base = 8; + ++endp; + if (*endp == 'x') { + base = 16; + ++endp; + } + } + for (n = 0; (c = *endp) && isxdigit(c); n += c) { + n *= base; + c -= '0'; + if (n >= TUINT_MAX - c*base) + error("overflow in number"); + endp++; + } + tok2str(); + yylval.sym = tmpsym(n); + + return NUMBER; +} + +static int +character(void) +{ + int c; + char *p; + + while (*endp != '\'') + ++endp; + return NUMBER; +} + +static int +string(void) +{ + int c; + size_t l; + char *s; + Symbol *sym = tmpsym(0); + + for (++endp; *endp != '"'; ++endp) + ; + ++endp; + tok2str(); + yylval.sym = sym; + /* FIXME: this memory is not freed ever */ + l = yylen-2; + s = memcpy(xmalloc(l+1), yytext+1, l); + s[l] = '\0'; + sym->name.buf = s; + + return STRING; +} + +static int +operator(void) +{ + int c; + + ++endp; + if ((c = *textp) == '>') + c = follow('=', '>', LE, SHL, '>'); + else if (c == '<') + c = follow('=', '<', GE, SHR, '>'); + tok2str(); + + return c; +} + +int +next(void) +{ + int c; + + while (isspace(*textp)) + ++textp; + + endp = textp; + + switch (c = *textp) { + case '\0': + strcpy(yytext, "EOS"); + yylen = 3; + c = EOS; + break; + case '"': + c = string(); + break; + case '\'': + c = character(); + break; + case '%': + c = (regmode ? iden : operator)(); + break; + case '_': + c = iden(); + break; + default: + if (isdigit(c)) + c = number(); + else if (isalpha(c)) + c = iden(); + else + c = operator(); + break; + } + return yytoken = c; +} + +void +expect(int token) +{ + if (yytoken != token) + unexpected(); + next(); +} + +void +unexpected(void) +{ + error("unexpected '%s'", yytext); +} + +void +error(char *msg, ...) +{ + va_list va; + struct input *ip; + + assert(isp > inputs); + ip = &isp[-1]; + + va_start(va, msg); + fprintf(stderr, "as:%s:%u: ", ip->fname, ip->lineno); + vfprintf(stderr, msg, va); + putc('\n', stderr); + nerrors++; + va_end(va); + + if (nerrors == 10) + die("as: too many errors"); + longjmp(recover, 1); +} + +Node * +getreg(void) +{ + Node *np; + + np = node(REG, NULL, NULL); + np->sym = yylval.sym; + np->addr = AREG; + expect(REG); + return np; +} + +void +regctx(int mode) +{ + regmode = mode; +} + +Node * +operand(char **strp) +{ + int imm = 0; + Node *np; + + textp = *strp; + regctx(1); + switch (next()) { + case EOS: + np = NULL; + break; + case REG: + np = getreg(); + break; + case STRING: + np = node(yytoken, NULL, NULL); + np->sym = yylval.sym; + np->addr = ASTR; + next(); + break; + case '$': + next(); + imm = 1; + default: + if (!imm) { + np = moperand(); + } else { + np = expr(); + np->addr = AIMM; + } + } + if (yytoken != ',' && yytoken != EOS) + error("trailing characters in expression '%s'", textp); + *strp = endp; + + return np; +} + +Node ** +getargs(char *s) +{ + Node **ap; + static Node *args[NARGS]; + + if (!s) + return NULL; + + for (ap = args; ap < &args[NARGS-1]; ++ap) { + if ((*ap = operand(&s)) == NULL) + return args; + } + error("too many arguments in one instruction"); +} + +static char * +field(char **oldp, size_t *siz) +{ + char *s, *t, *begin; + size_t n; + + if ((begin = *oldp) == NULL) + return NULL; + + for (s = begin; isspace(*s) && *s != '\t'; ++s) + ; + if (*s == '\0' || *s == '/' || *s == ';') { + *s = '\0'; + return *oldp = NULL; + } + + for (t = s; *t && *t != '\t'; ++t) + ; + if (*t == '\t') + *t++ = '\0'; + *siz -= begin - t; + *oldp = t; + + while (t >= s && isspace(*t)) + *t-- = '\0'; + return (*s != '\0') ? s : NULL; +} + +static int +validlabel(char *name) +{ + int c; + + while ((c = *name++) != '\0') { + if (isalnum(c)) + continue; + switch (c) { + case '_': + case '-': + case '.': + case '$': + continue; + case ':': + if (*name != '\0') + return 0; + *--name = '\0'; + continue; + default: + return 0; + } + } + return 1; +} + +static int +extract(char *s, size_t len, struct line *lp) +{ + int r = 0; + + if (lp->label = field(&s, &len)) + r++; + if (lp->op = field(&s, &len)) + r++; + if (lp->args = field(&s, &len)) + r++; + + if (s && *s && *s != '/') + error("trailing characters at the end of the line"); + if (lp->label && !validlabel(lp->label)) + error("incorrect label name '%s'", lp->label); + + return r; +} + +static void +comment(FILE *fp) +{ + int c; + + while ((c = getc(fp)) != EOF) { + if (c != '*') + continue; + if ((c = getc(fp)) == '/') + return; + ungetc(c, fp); + } +} + +static size_t +getline(FILE *fp, char buff[MAXLINE]) +{ + int c; + char *bp; + + for (bp = buff; (c = getc(fp)) != EOF; *bp++ = c) { + if (c == '\n') + break; + if (c == '/') { + if ((c = getc(fp)) != '*') { + ungetc(c, fp); + c = '/'; + } else { + comment(fp); + c = ' '; + } + } else if (c > UCHAR_MAX) { + error("invalid character '%x'", c); + } + if (bp == &buff[MAXLINE-1]) + error("line too long"); + } + *bp = '\0'; + + return bp - buff; +} + +int +nextline(FILE *fp, struct line *lp) +{ + struct input *ip; + size_t n; + static char buff[MAXLINE]; + + assert(isp > inputs); +repeat: + if (isp == inputs) + return 0; + ip = &isp[-1]; + if (feof(ip->fp)) { + delinput(); + goto repeat; + } + n = getline(ip->fp, buff); + if (++ip->lineno == 0) + die("as: %s: file too long", infile); + if (n == 0) + goto repeat; + if (extract(buff, n, lp) == 0) + goto repeat; + return 1; +} + +void +addinput(char *fname) +{ + FILE *fp; + + if (isp == &inputs[NR_INPUTS]) + die("as: too many included files"); + if ((fp = fopen(fname, "r")) == NULL) + die("as: %s: %s", fname, strerror(errno)); + isp->fname = xstrdup(fname); + isp->fp = fp; + isp->lineno = 0; + ++isp; +} + +int +delinput(void) +{ + if (isp == inputs) + return EOF; + --isp; + if (fclose(isp->fp) == EOF) + die("as: %s: %s", isp->fname, strerror(errno)); + free(isp->fname); + return 0; +} diff --git a/src/as/symbol.c b/src/as/symbol.c @@ -0,0 +1,291 @@ +static char sccsid[] = "@(#) ./as/symbol.c"; + +#include <ctype.h> +#include <stdio.h> +#include <stdint.h> +#include <string.h> + +#include <scc/scc.h> +#include "as.h" + +#define HASHSIZ 64 +#define NALLOC 10 + +Section *cursec, *seclist; +Section *sabs, *sbss, *sdata, *stext; +Symbol *linesym, *symlist; +int pass; + +static Symbol *hashtbl[HASHSIZ], *symlast; +static Alloc *tmpalloc; + + +#ifndef NDEBUG +void +dumpstab(char *msg) +{ + Symbol **bp, *sym; + + fprintf(stderr, "%s\n", msg); + for (bp = hashtbl; bp < &hashtbl[HASHSIZ]; ++bp) { + if (*bp == NULL) + continue; + + fprintf(stderr, "[%d]", (int) (bp - hashtbl)); + for (sym = *bp; sym; sym = sym->hash) { + fprintf(stderr, " -> %s:%0X:%0X", + sym->name.buf, sym->flags, sym->value); + } + putc('\n', stderr); + } +} +#endif + +Symbol * +lookup(char *name) +{ + unsigned h; + Symbol *sym, **list; + int c, symtype; + char *t, *s; + + h = 0; + for (s = name; c = *s; ++s) + h = h*33 ^ c; + h &= HASHSIZ-1; + + c = toupper(*name); + list = &hashtbl[h]; + for (sym = *list; sym; sym = sym->hash) { + t = sym->name.buf; + if (c == toupper(*t) && !casecmp(t, name)) + return sym; + } + + sym = xmalloc(sizeof(*sym)); + sym->name = newstring(name); + sym->flags = 0; + sym->size = sym->value = 0; + sym->section = cursec; + sym->hash = *list; + sym->next = NULL; + + *list = sym; + if (symlast) + symlast->next = sym; + symlast = sym; + if (!symlist) + symlist = sym; + + return sym; +} + +Symbol * +deflabel(char *name) +{ + static Symbol *cursym; + Symbol *sym; + char label[MAXSYM+1]; + + if (*name == '.') { + int r; + + if (!cursym) { + error("local label '%s' without global label", name); + return NULL; + } + r = snprintf(label, sizeof(label), + "%s%s", + cursym->name.buf, name); + if (r == sizeof(label)) { + error("local label '%s' in '%s' produces too long symbol", + name, cursym->name.buf); + return NULL; + } + name = label; + } + + sym = lookup(name); + if (pass == 1 && (sym->flags & FDEF)) + error("redefinition of label '%s'", name); + if (cursec->flags & SABS) + sym->flags |= FABS; + sym->flags |= FDEF; + sym->value = cursec->curpc; + sym->section = cursec; + + if (*name != '.') + cursym = sym; + return sym; +} + +int +toobig(Node *np, int type) +{ + /* TODO */ + return 0; +} + +static void +incpc(int siz) +{ + TUINT pc, curpc; + + pc = cursec->pc; + curpc = cursec->curpc; + + cursec->curpc += siz; + cursec->pc += siz; + + if (pass == 2) + return; + + if (cursec->pc > cursec->max) + cursec->max = cursec->pc; + + if (pc > cursec->pc || + curpc > cursec->curpc || + cursec->curpc > maxaddr || + cursec->pc > maxaddr) { + die("as: address overflow in section '%s'"); + } +} + +static int +secflags(char *attr) +{ + int c, flags; + + if (!attr) + return 0; + + for (flags = 0; c = *attr++; ) { + switch (c) { + case 'w': + flags |= SWRITE; + break; + case 'r': + flags |= SREAD; + break; + case 'x': + flags |= SEXEC; + break; + case 'f': + flags |= SFILE; + break; + case 'l': + flags |= SLOAD; + break; + case 'a': + flags |= SABS; + break; + } + } + + return flags; +} + +Section * +setsec(char *name, char *attr) +{ + Section *sec; + Symbol *sym; + + cursec = NULL; + sym = lookup(name); + if (sym->flags & ~FSECT) + error("invalid section name '%s'", name); + + if ((sec = sym->section) == NULL) { + sec = xmalloc(sizeof(*sec)); + sec->mem = NULL; + sec->sym = sym; + sec->base = sec->max = sec->pc = sec->curpc = 0; + sec->next = seclist; + sec->flags = 0; + sec->fill = 0; + sec->aligment = 0; + sec->next = seclist; + seclist = sec; + + sym->section = sec; + sym->flags = FSECT; + } + sec->flags |= secflags(attr); + + return cursec = sec; +} + +void +isecs(void) +{ + sabs = setsec(".abs", "rwx"); + sbss = setsec(".bss", "rwf"); + sdata = setsec(".data", "rw"); + stext = setsec(".text", "rx"); +} + +void +cleansecs(void) +{ + Section *sec; + TUINT siz; + + for (sec = seclist; sec; sec = sec->next) { + sec->curpc = sec->pc = sec->base; + if (pass == 1 || sec->flags & SFILE) + continue; + + siz = sec->max - sec->base; + if (siz > SIZE_MAX) + die("as: out of memory"); + sec->mem = xmalloc(sec->max - sec->base); + } + cursec = stext; +} + +void +emit(char *bytes, int n) +{ + if (cursec->mem) { + size_t len = cursec->pc - cursec->base; + memcpy(&cursec->mem[len], bytes, n); + } + incpc(n); +} + +Symbol * +tmpsym(TUINT val) +{ + Symbol *sym; + + if (!tmpalloc) + tmpalloc = alloc(sizeof(*sym), NALLOC); + sym = new(tmpalloc); + sym->value = val; + sym->section = NULL; + sym->flags = FABS; + + return sym; +} + +void +killtmp(void) +{ + if (!tmpalloc) + return; + dealloc(tmpalloc); + tmpalloc = NULL; +} + +String +newstring(char *s) +{ + size_t len = strlen(s) + 1; + String str; + + str.offset = 0; + str.buf = xmalloc(len); + memcpy(str.buf, s, len); + return str; +} diff --git a/src/as/target/amd64.mk b/src/as/target/amd64.mk @@ -0,0 +1,10 @@ +AMD64_OBJ = $(OBJS) \ + target/x86/amd64tbl.o \ + target/x86/amd64.o \ + target/x86/ins.o \ + +target/x86/amd64tbl.c: target/x86/x86.dat target/x86/rules.dat + ./mktbl -f x86 -c amd64 + +$(LIBEXEC)/as-amd64: $(AMD64_OBJ) + $(CC) $(SCC_LDFLAGS) $(AMD64_OBJ) -lscc -o $@ diff --git a/src/as/target/i286.mk b/src/as/target/i286.mk @@ -0,0 +1,10 @@ +I286_OBJ = $(OBJS) \ + target/x86/i286tbl.o \ + target/x86/i286.o \ + target/x86/ins.o \ + +target/x86/i286tbl.c: target/x86/x86.dat target/x86/rules.dat + ./mktbl -f x86 -c i286 + +$(LIBEXEC)/as-i286: $(I286_OBJ) + $(CC) $(SCC_LDFLAGS) $(I286_OBJ) -lscc -o $@ diff --git a/src/as/target/i386.mk b/src/as/target/i386.mk @@ -0,0 +1,10 @@ +I386_OBJ = $(OBJS) \ + target/x86/i386tbl.o \ + target/x86/i386.o \ + target/x86/ins.o \ + +target/x86/i386tbl.c: target/x86/x86.dat target/x86/rules.dat + ./mktbl -f x86 -c i386 + +$(LIBEXEC)/as-i386: $(I386_OBJ) + $(CC) $(SCC_LDFLAGS) $(I386_OBJ) -lscc -o $@ diff --git a/src/as/target/x80/.gitignore b/src/as/target/x80/.gitignore @@ -0,0 +1 @@ +z80tbl.c diff --git a/src/as/target/x80/ins.c b/src/as/target/x80/ins.c @@ -0,0 +1,601 @@ +static char sccsid[] = "@(#) ./as/target/x80/ins.c"; + +#include <stdlib.h> +#include <string.h> + +#include <scc/scc.h> + +#include "../../as.h" +#include "proc.h" + +/* + * This implementation is based in: + * - Zilog Z80 CPU Specifications by Sean Young + * - Decoding Z80 opcodes - of use to disassembler and emulator + * writers - by Cristian Dinu. + */ + +static int +getclass(Node *np) +{ + if (np->addr != AREG) + return 0; + + switch (np->sym->value) { + case AREG_C: + return RCLASS | PCLASS | QCLASS | CCCLASS | SSCLASS; + case AREG_A: + case AREG_B: + case AREG_D: + case AREG_E: + return RCLASS | PCLASS | QCLASS; + case AREG_H: + case AREG_L: + return RCLASS; + case AREG_IXL: + case AREG_IXH: + return PCLASS; + case AREG_IYL: + case AREG_IYH: + return QCLASS; + case AREG_HL: + return DDCLASS | QQCLASS; + case AREG_BC: + case AREG_DE: + return DDCLASS | QQCLASS | PPCLASS | RRCLASS; + case AREG_SP: + return DDCLASS | PPCLASS | RRCLASS; + case AREG_AF: + return QQCLASS; + case AREG_IX: + return PPCLASS; + case AREG_IY: + return RRCLASS; + case AREG_PO: + case AREG_PE: + case AREG_P: + case AREG_M: + return CCCLASS; + case AREG_NZ: + case AREG_Z: + case AREG_NC: + return CCCLASS | SSCLASS; + default: + return 0; + } +} + +int +match(Op *op, Node **args) +{ + unsigned char *p; + int arg, class, rep, opt; + Node *np; + + if (!op->args) + return args == NULL; + + opt = rep = 0; + for (p = op->args; arg = *p; ++p) { + if (rep) + --p; + if ((np = *args++) == NULL) + return (rep|opt) != 0; + + switch (arg) { + case AOPT: + opt = 1; + break; + case AREP: + rep = 1; + break; + case AINDER_C: + arg = AREG_C; + goto indirect; + case AINDER_HL: + arg = AREG_HL; + goto indirect; + case AINDER_DE: + arg = AREG_DE; + goto indirect; + case AINDER_BC: + arg = AREG_BC; + goto indirect; + case AINDER_IX: + arg = AREG_IX; + goto indirect; + case AINDER_IY: + arg = AREG_IY; + goto indirect; + case AINDER_SP: + arg = AREG_SP; + indirect: + if (np->addr != AINDIR) + return 0; + np = np->left; + case AREG_A: + case AREG_I: + case AREG_R: + case AREG_F: + case AREG_HL: + case AREG_BC: + case AREG_DE: + case AREG_IY: + case AREG_IX: + case AREG_SP: + case AREG_AF: + case AREG_AF_: + if (np->addr != AREG || np->sym->value != arg) + return 0; + break; + case AREG_RCLASS: + class = RCLASS; + goto check_class; + case AREG_PCLASS: + class = PCLASS; + goto check_class; + case AREG_QCLASS: + class = QCLASS; + goto check_class; + case AREG_QQCLASS: + class = QQCLASS; + goto check_class; + case AREG_PPCLASS: + class = PPCLASS; + goto check_class; + case AREG_RRCLASS: + class = RRCLASS; + goto check_class; + case AREG_CCCLASS: + class = CCCLASS; + goto check_class; + case AREG_SSCLASS: + class = SSCLASS; + goto check_class; + case AREG_DDCLASS: + class = DDCLASS; + check_class: + if ((getclass(np) & class) == 0) + return 0; + break; + case AINDEX_IY: + arg = AREG_IY; + goto index_address; + case AINDEX_IX: + arg = AREG_IX; + index_address: + if (np->addr != AINDEX) + return 0; + if (np->left->left->sym->value != arg) + return 0; + if (toobig(np, arg)) + error("overflow in index"); + break; + case ARST: + if (np->addr != AIMM) + return 0; + if ((np->sym->value & ~0x38) != 0) + return 0; + break; + case AZERO: + case AIMM3: + case AIMM8: + case AIMM16: + case AIMM32: + case AIMM64: + if (np->addr != AIMM) + return 0; + if (toobig(np, arg)) + error("overflow in immediate operand"); + break; + case ASYM: + if (np->addr != AIMM || np->op != IDEN) + return 0; + break; + case ADIRECT: + case ASTR: + if (np->addr != arg) + return 0; + break; + default: + abort(); + } + } + + return *args == NULL; +} + +/* + * (expr) -> ADIRECT + * (REG) -> AINDIR + * (REG + expr) -> AINDEX + * (REG - expr) -> AINDEX + * expr (REG) -> AINDEX + */ +Node * +moperand(void) +{ + int op; + Node *np, *dir, *off, *reg; + + dir = off = reg = NULL; + if (accept('(')) { + if (yytoken != REG) { + dir = expr(); + } else { + reg = getreg(); + switch (yytoken) { + case '+': + case '-': + off = expr(); + case ')': + break; + default: + unexpected(); + } + } + } else { + off = expr(); + expect('('); + reg = getreg(); + } + expect(')'); + + if (dir) { + op = ADIRECT; + np = dir; + } else if (off) { + np = node(AREG_OFF, reg, off); + op = AINDEX; + } else { + np = reg; + op = AINDIR; + } + np = node(op, np, NULL); + np->addr = op; + return np; +} + +static int +reg2int(Node *np) +{ + switch (np->sym->value) { + case AREG_F: + case AREG_B: return 0; + case AREG_C: return 1; + case AREG_D: return 2; + case AREG_E: return 3; + case AREG_IXH: + case AREG_IYH: + case AREG_H: return 4; + case AREG_IXL: + case AREG_IYL: + case AREG_L: return 5; + case AREG_A: return 7; + case AREG_BC: return 0; + case AREG_DE: return 1; + case AREG_HL: + case AREG_IX: + case AREG_IY: return 2; + case AREG_AF: + case AREG_SP: return 3; + default: abort(); + } +} + +static int +cc2int(Node *np) +{ + switch (np->sym->value) { + case AREG_NZ: return 0; + case AREG_Z: return 1; + case AREG_NC: return 2; + case AREG_C: return 3; + case AREG_PO: return 4; + case AREG_PE: return 5; + case AREG_P: return 6; + case AREG_M: return 7; + default: abort(); + } +} + +static int +ss2int(Node *np) +{ + switch (np->sym->value) { + case AREG_NZ: return 4; + case AREG_Z: return 5; + case AREG_NC: return 6; + case AREG_C: return 7; + default: abort(); + } +} + +void +dir(Op *op, Node **args) +{ + Node *imm; + unsigned char buf[4]; + unsigned val; + int n = op->size; + + imm = (args[1]->addr == ADIRECT) ? args[1] : args[0]; + imm = imm->left; + memcpy(buf, op->bytes, n); + val = imm->sym->value; + buf[n-1] = val >> 8; + buf[n-2] = val; + emit(buf, n); +} + +void +ld8(Op *op, Node **args) +{ + Node *par1 = args[0], *par2 = args[1]; + int n = op->size, i = n;; + unsigned regval = 0; + unsigned char buf[4]; + + memcpy(buf, op->bytes, n); + + if (par1->addr == AREG) + regval |= reg2int(par1) << 3; + if (par2->addr == AREG) + regval |= reg2int(par2); + else if (par2->addr == AIMM) + buf[--i] = par2->sym->value; + + buf[--i] |= regval; + emit(buf, n); +} + +void +alu16(Op *op, Node **args) +{ + Node *par; + int n = op->size; + unsigned val; + unsigned char buf[4]; + + par = (args[1]) ? args[1] : args[0]; + val = reg2int(par); + memcpy(buf, op->bytes, n); + buf[n-1] |= val << 4; + emit(buf, n); +} + +void +ld16(Op *op, Node **args) +{ + Node *dst, *src, *tmp; + int n = op->size; + unsigned val; + unsigned char buf[4]; + + dst = args[0]; + src = args[1]; + if (!src) { + alu16(op, args); + return; + } + + if (dst->addr != AREG) { + tmp = src; + src = dst; + dst = tmp; + } + + memcpy(buf, op->bytes, n); + if (src->addr == ADIRECT) + src = src->left; + val = src->sym->value; + buf[n-1] = val >> 8; + buf[n-2] = val; + buf[n-3] |= reg2int(dst) << 4; + emit(buf, n); +} + +void +alu8(Op *op, Node **args) +{ + Node *par = args[1]; + unsigned char buf[4]; + int n = op->size, shift; + unsigned val; + + if (args[1]) { + shift = 0; + par = args[1]; + } else { + shift = 3; + par = args[0]; + } + + switch (par->addr) { + case AIMM: + val = par->sym->value; + break; + case AREG: + val = reg2int(par) << shift; + break; + case AINDEX: + val = par->left->right->sym->value; + break; + case AINDIR: + val = 0; + break; + default: + abort(); + } + + memcpy(buf, op->bytes, n); + buf[n-1] |= val; + emit(buf, n); +} + +void +idx(Op *op, Node **args) +{ + Node *tmp, *idx, *imm, *reg; + unsigned char buf[4]; + int n = op->size, i = n, shift = 0; + + imm = reg = NULL; + if (args[0]->addr != AINDEX) { + shift = 3; + tmp = args[0]; + args[0] = args[1]; + args[1] = tmp; + } + idx = args[0]->left->right; + + if (args[1]->addr == AREG) + reg = args[1]; + else + imm = args[1]; + + memcpy(buf, op->bytes, n); + + if (imm) + buf[--i] = imm->sym->value; + buf[--i] = idx->sym->value; + if (reg) + buf[--i] |= reg2int(reg) << shift; + + emit(buf, n); +} + +void +inout(Op *op, Node **args) +{ + Node *port, *value; + unsigned val; + int n = op->size; + unsigned char buf[5]; + + port = args[0]; + value = args[1]; + if (port->addr != ADIRECT && port->addr != AINDIR) { + value = port; + port = args[1]; + } + + if (port->addr == ADIRECT) + val = port->left->sym->value; + else if (value->addr == AREG) + val = reg2int(value) << 3; + else + val = 0; + + memcpy(buf, op->bytes, n); + buf[n-1] |= val; + emit(buf, n); +} + +void +rot_bit(Op *op, Node **args) +{ + Node *par = args[0]; + unsigned char buf[5]; + int n = op->size; + unsigned val, npar = 0; + + memcpy(buf, op->bytes, n); + + par = args[0]; + if (par->addr == AIMM) { + buf[n-1] |= par->sym->value << 3; + par = args[npar = 1]; + } + + switch (par->addr) { + case AINDEX: + val = par->left->right->sym->value; + buf[n-2] = val; + par = args[npar+1]; + if (!par) + break; + case AREG: + val = reg2int(par); + buf[n-1] |= val; + case AINDIR: + break; + default: + abort(); + } + + emit(buf, n); +} + +void +im(Op *op, Node **args) +{ + unsigned val = args[0]->sym->value; + unsigned char buf[4]; + int n = op->size; + + if (val > 0) + ++val; + + memcpy(buf, op->bytes, n); + buf[n-1] |= val << 3; + emit(buf, n); +} + +void +branch(int relative, Op *op, Node **args) +{ + unsigned char buf[4]; + Node *flag, *imm; + int n = op->size, i = n; + unsigned val; + int (*fun)(Node *); + + flag = imm = NULL; + if (args[0]->addr == AREG) { + flag = args[0]; + imm = args[1]; + } else if (args[0]->addr == AIMM) { + imm = args[0]; + } + memcpy(buf, op->bytes, n); + + if (imm) { + val = imm->sym->value; + if (!relative) + buf[--i] = val >> 8; + else + val -= cursec->curpc - 2; + buf[--i] = val; + + } + if (flag) { + fun = (relative) ? ss2int : cc2int; + buf[--i] |= (*fun)(flag) << 3; + } + + + emit(buf, n); +} + +void +jp(Op *op, Node **args) +{ + branch(0, op, args); +} + +void +jr(Op *op, Node **args) +{ + branch(1, op, args); +} + +void +rst(Op *op, Node **args) +{ + unsigned char buf[1]; + + buf[0] = op->bytes[0]; + buf[0] |= args[0]->sym->value; + emit(buf, 1); +} diff --git a/as/target/x80/proc.h b/src/as/target/x80/proc.h diff --git a/as/target/x80/rules.dat b/src/as/target/x80/rules.dat diff --git a/as/target/x80/x80.dat b/src/as/target/x80/x80.dat diff --git a/src/as/target/x80/z80.c b/src/as/target/x80/z80.c @@ -0,0 +1,65 @@ +static char sccsid[] = "@(#) ./as/target/x80/z80.c"; + +#include <stdlib.h> + +#include <scc/scc.h> + +#include "../../as.h" +#include "../x80/proc.h" + +TUINT maxaddr = 0xFFFFFFFF; +int endian = LITTLE_ENDIAN; + +void +iarch(void) +{ + static struct { + char *name; + char type; + } regs[] = { + "AF", AREG_AF, + "A", AREG_A, + "F", AREG_F, + + "BC", AREG_BC, + "B", AREG_B, + "C", AREG_C, + + "HL", AREG_HL, + "H", AREG_H, + "L", AREG_L, + + "DE", AREG_DE, + "D", AREG_D, + "E", AREG_E, + + "IX", AREG_IX, + "IXL", AREG_IXL, + "IXH", AREG_IXH, + + "IY", AREG_IY, + "IYL", AREG_IYL, + "IYH", AREG_IYH, + + "R", AREG_R, + "I", AREG_I, + "AF'", AREG_AF_, + "SP", AREG_SP, + + "NZ", AREG_NZ, + "Z", AREG_Z, + "NC", AREG_NC, + "PO", AREG_PO, + "PE", AREG_PE, + "P", AREG_P, + "M", AREG_M, + + NULL, + }, *bp; + + for (bp = regs; bp->name; ++bp) { + Symbol *sym = lookup(bp->name); + sym->flags = FREG; + sym->value = bp->type; + } +} diff --git a/src/as/target/x86/.gitignore b/src/as/target/x86/.gitignore @@ -0,0 +1,3 @@ +amd64tbl.c +i286tbl.c +i386tbl.c diff --git a/src/as/target/x86/amd64.c b/src/as/target/x86/amd64.c @@ -0,0 +1,13 @@ +static char sccsid[] = "@(#) ./as/target/x86/amd64.c"; + +#include <scc/scc.h> + +#include "../../as.h" + +TUINT maxaddr = 0xFFFFFFFFFFFFFFFF; +int endian = LITTLE_ENDIAN; + +void +iarch(void) +{ +} diff --git a/src/as/target/x86/i286.c b/src/as/target/x86/i286.c @@ -0,0 +1,54 @@ +static char sccsid[] = "@(#) ./as/target/x86/i286.c"; + +#include <scc/scc.h> + +#include "../../as.h" +#include "../x86/proc.h" + +TUINT maxaddr = 0xFFFF; +int endian = LITTLE_ENDIAN; +int left2right = 0; + +void +iarch(void) +{ + static struct { + char *name; + char type; + } regs[] = { + "CS", AREG_CS, + "DS", AREG_DS, + "SS", AREG_SS, + "ES", AREG_ES, + + "AX", AREG_AX, + "AL", AREG_AL, + "AH", AREG_AH, + + "BX", AREG_BX, + "BL", AREG_BL, + "BH", AREG_BH, + + "CX", AREG_CX, + "CL", AREG_CL, + "CH", AREG_CH, + + "DX", AREG_DX, + "DL", AREG_DL, + "DH", AREG_DH, + + "SI", AREG_SI, + "DI", AREG_DI, + + "SP", AREG_SP, + "BP", AREG_BP, + + NULL + }, *bp; + + for (bp = regs; bp->name; ++bp) { + Symbol *sym = lookup(bp->name); + sym->flags = FREG; + sym->value = bp->type; + } +} diff --git a/src/as/target/x86/i386.c b/src/as/target/x86/i386.c @@ -0,0 +1,101 @@ +static char sccsid[] = "@(#) ./as/target/x86/i386.c"; + +#include <scc/scc.h> + +#include "../../as.h" +#include "../x86/proc.h" + +TUINT maxaddr = 0xFFFFFFFF; +int endian = LITTLE_ENDIAN; + +void +iarch(void) +{ + static struct { + char *name; + char type; + } regs[] = { + "CS", AREG_CS, + "DS", AREG_DS, + "SS", AREG_SS, + "ES", AREG_ES, + "FS", AREG_FS, + "GS", AREG_GS, + + "AX", AREG_AX, + "AL", AREG_AL, + "AH", AREG_AH, + "EAX", AREG_EAX, + + "BC", AREG_BX, + "BL", AREG_BL, + "BH", AREG_BH, + "EBX", AREG_EBX, + + "CX", AREG_CX, + "CL", AREG_CL, + "CH", AREG_CH, + "ECX", AREG_ECX, + + "DX", AREG_DX, + "DL", AREG_DL, + "DH", AREG_DH, + "EDX", AREG_EDX, + + "SI", AREG_SI, + "ESI", AREG_ESI, + "DI", AREG_DI, + "EDI", AREG_EDI, + + "SP", AREG_SP, + "ESP", AREG_ESP, + + "BP", AREG_BP, + "EBP", AREG_EBP, + + "R0", AREG_R0, + "MM0", AREG_MM0, + "R1", AREG_R1, + "MM1", AREG_MM1, + "R2", AREG_R2, + "MM2", AREG_MM2, + "R3", AREG_R3, + "MM3", AREG_MM3, + "R4", AREG_R4, + "MM4", AREG_MM4, + "R5", AREG_R5, + "MM5", AREG_MM5, + "R6", AREG_R6, + "MM6", AREG_MM6, + "R7", AREG_R7, + "MM7", AREG_MM7, + + "XMM0", AREG_XMM0, + "XMM1", AREG_XMM1, + "XMM2", AREG_XMM2, + "XMM3", AREG_XMM3, + "XMM4", AREG_XMM4, + "XMM5", AREG_XMM5, + "XMM6", AREG_XMM6, + "XMM7", AREG_XMM7, + + "YMM0", AREG_YMM0, + "YMM1", AREG_YMM1, + "YMM2", AREG_YMM2, + "YMM3", AREG_YMM3, + "YMM4", AREG_YMM4, + "YMM5", AREG_YMM5, + "YMM6", AREG_YMM6, + "YMM7", AREG_YMM7, + + "MXCSR", AREG_MXCSR, + + NULL + }, *bp; + + for (bp = regs; bp->name; ++bp) { + Symbol *sym = lookup(bp->name); + sym->flags = FREG; + sym->value = bp->type; + } +} diff --git a/src/as/target/x86/ins.c b/src/as/target/x86/ins.c @@ -0,0 +1,302 @@ +static char sccsid[] = "@(#) ./as/target/x86/ins.c"; + +#include <stdlib.h> + +#include <scc/scc.h> + +#include "../../as.h" +#include "proc.h" + +#define addrbyte(mod, reg, rm) ((mod) << 6 | (reg) << 3 | (rm)) + +enum addr_mode { + MEM_MODE = 0, + MEM8_MODE = 1, + MEM16_MODE = 2, + REG_MODE = 3, +}; + +static int +getclass(Node *np) +{ + if (np->addr != AREG) + return 0; + + switch (np->sym->value) { + case AREG_AL: + case AREG_AH: + case AREG_BL: + case AREG_BH: + case AREG_CL: + case AREG_CH: + case AREG_DL: + case AREG_DH: + return R8CLASS; + + case AREG_AX: + case AREG_BX: + case AREG_CX: + case AREG_DX: + case AREG_DI: + case AREG_SI: + case AREG_SP: + case AREG_BP: + return R16CLASS; + + case AREG_CS: + case AREG_DS: + case AREG_SS: + case AREG_ES: + case AREG_FS: + case AREG_GS: + + case AREG_EFLAGS: + case AREG_CF: + case AREG_PF: + case AREG_AF: + case AREG_ZF: + case AREG_SF: + case AREG_TF: + case AREG_IF: + case AREG_DF: + case AREG_OF: + case AREG_IOPL: + case AREG_NT: + case AREG_RF: + case AREG_VM: + case AREG_AC: + case AREG_VIF: + case AREG_VIP: + case AREG_ID: + + case AREG_EAX: + case AREG_RAX: + + case AREG_EBX: + case AREG_RBX: + + case AREG_ECX: + case AREG_RCX: + + case AREG_EDX: + case AREG_RDX: + + case AREG_SIL: + case AREG_ESI: + case AREG_RSI: + case AREG_DIL: + case AREG_EDI: + case AREG_RDI: + + case AREG_SPL: + case AREG_ESP: + case AREG_RSP: + + case AREG_BPL: + case AREG_EBP: + case AREG_RBP: + + case AREG_R0: + case AREG_MM0: + case AREG_R1: + case AREG_MM1: + case AREG_R2: + case AREG_MM2: + case AREG_R3: + case AREG_MM3: + case AREG_R4: + case AREG_MM4: + case AREG_R5: + case AREG_MM5: + case AREG_R6: + case AREG_MM6: + case AREG_R7: + case AREG_MM7: + + case AREG_R8: + case AREG_R8L: + case AREG_R8W: + case AREG_R9: + case AREG_R9L: + case AREG_R9W: + case AREG_R10: + case AREG_R10L: + case AREG_R10W: + case AREG_R11: + case AREG_R11L: + case AREG_R11W: + case AREG_R12: + case AREG_R12L: + case AREG_R12W: + case AREG_R13: + case AREG_R13L: + case AREG_R13W: + case AREG_R14: + case AREG_R14L: + case AREG_R14W: + case AREG_R15: + case AREG_R15L: + case AREG_R15W: + + case AREG_XMM0: + case AREG_XMM1: + case AREG_XMM2: + case AREG_XMM3: + case AREG_XMM4: + case AREG_XMM5: + case AREG_XMM6: + case AREG_XMM7: + case AREG_XMM8: + case AREG_XMM9: + case AREG_XMM10: + case AREG_XMM11: + case AREG_XMM12: + case AREG_XMM13: + case AREG_XMM14: + case AREG_XMM15: + + case AREG_YMM0: + case AREG_YMM1: + case AREG_YMM2: + case AREG_YMM3: + case AREG_YMM4: + case AREG_YMM5: + case AREG_YMM6: + case AREG_YMM7: + case AREG_YMM8: + case AREG_YMM9: + case AREG_YMM10: + case AREG_YMM11: + case AREG_YMM12: + case AREG_YMM13: + case AREG_YMM14: + case AREG_YMM15: + + case AREG_MXCSR: + return 0; + default: + abort(); + } +} + +int +match(Op *op, Node **args) +{ + unsigned char *p; + int arg, class, rep, opt; + Node *np; + + if (!op->args) + return args == NULL; + + opt = rep = 0; + for (p = op->args; arg = *p; ++p) { + if (rep) + --p; + if ((np = *args++) == NULL) + return (rep|opt) != 0; + + switch (arg) { + case AOPT: + opt = 1; + break; + case AREP: + rep = 1; + break; + case AREG_R8CLASS: + class = R8CLASS; + goto check_class; + case AREG_R16CLASS: + class = R16CLASS; + check_class: + if ((getclass(np) & class) == 0) + return 0; + break; + case AIMM8: + case AIMM16: + case AIMM32: + case AIMM64: + if (np->addr != AIMM) + return 0; + if (toobig(np, arg)) + error("overflow in immediate operand"); + break; + case ASYM: + if (np->addr != AIMM || np->op != IDEN) + return 0; + break; + case ADIRECT: + case ASTR: + if (np->addr != arg) + return 0; + break; + default: + abort(); + } + } + + return *args == NULL; +} + +Node * +moperand(void) +{ +} + +static int +reg8toint(Node *np) +{ + switch (np->sym->value) { + case AREG_AL: return 0; + case AREG_CL: return 1; + case AREG_DL: return 2; + case AREG_BL: return 3; + case AREG_AH: return 4; + case AREG_CH: return 5; + case AREG_DH: return 6; + case AREG_BH: return 7; + default: abort(); + } +} + +void +reg8_reg8(Op *op, Node **args) +{ + int src, dst; + char buf[2]; + + src = reg8toint(args[0]); + dst = reg8toint(args[1]); + buf[0] = op->bytes[0]; + buf[1] = addrbyte(REG_MODE, src, dst); + emit(buf, 2); +} + +static int +reg16toint(Node *np) +{ + switch (np->sym->value) { + case AREG_AX: return 0; + case AREG_CX: return 1; + case AREG_DX: return 2; + case AREG_BX: return 3; + case AREG_SP: return 4; + case AREG_BP: return 5; + case AREG_SI: return 6; + case AREG_DI: return 7; + default: abort(); + } +} + +void +reg16_reg16(Op *op, Node **args) +{ + int src, dst; + char buf[2]; + + src = reg16toint(args[0]); + dst = reg16toint(args[1]); + buf[0] = op->bytes[0]; + buf[1] = addrbyte(REG_MODE, src, dst); + emit(buf, 2); +} diff --git a/as/target/x86/nasm.dat b/src/as/target/x86/nasm.dat diff --git a/as/target/x86/proc.h b/src/as/target/x86/proc.h diff --git a/as/target/x86/rules.dat b/src/as/target/x86/rules.dat diff --git a/as/target/x86/x86.dat b/src/as/target/x86/x86.dat diff --git a/src/as/target/z80.mk b/src/as/target/z80.mk @@ -0,0 +1,10 @@ +Z80_OBJ = $(OBJS) \ + target/x80/z80tbl.o \ + target/x80/z80.o \ + target/x80/ins.o \ + +target/x80/z80tbl.c: target/x80/x80.dat target/x80/rules.dat + ./mktbl -f x80 -c z80 + +$(LIBEXEC)/as-z80: $(OBJ) $(Z80_OBJ) + $(CC) $(SCC_LDFLAGS) $(Z80_OBJ) -lscc -o $@ diff --git a/src/cc1/Makefile b/src/cc1/Makefile @@ -0,0 +1,38 @@ +.POSIX: + +PROJECTDIR = ../.. +include $(PROJECTDIR)/scripts/rules.mk + +OBJS = types.o \ + decl.o \ + lex.o \ + error.o \ + symbol.o \ + main.o \ + expr.o \ + code.o \ + stmt.o \ + cpp.o \ + fold.o \ + init.o \ + builtin.o \ + +TARGET = $(LIBEXEC)/cc1-amd64-sysv \ + $(LIBEXEC)/cc1-arm64-sysv \ + $(LIBEXEC)/cc1-i386-sysv \ + $(LIBEXEC)/cc1-z80-scc \ + +all: $(TARGET) + +$(TARGET): $(LIBDIR)/libscc.a + +dep: inc-dep + +clean: + rm -f target/*/*.o + +include target/amd64-sysv/arch.mk +include target/arm64-sysv/arch.mk +include target/i386-sysv/arch.mk +include target/z80-scc/arch.mk +include deps.mk diff --git a/cc1/TODO b/src/cc1/TODO diff --git a/src/cc1/builtin.c b/src/cc1/builtin.c @@ -0,0 +1,121 @@ +static char sccsid[] = "@(#) ./cc1/builtin.c"; + +#include <stdio.h> + +#include <scc/scc.h> +#include "cc1.h" + +static Node * +builtin_va_arg(Symbol *sym) +{ + Node *np, *ap; + Type *tp; + + ap = assign(); + expect(','); + tp = typename(); + + if (!valid_va_list(ap->type)) { + errorp("incorrect parameters for va_arg"); + goto error; + } + if (tp == booltype || + tp == chartype || tp == uchartype || tp == schartype || + tp == shortype || tp == ushortype) { + warn("bool, char and short are promoted to int when passed through '...'"); + tp = (tp->prop & TSIGNED) ? inttype : uinttype; + } + + np = node(OBUILTIN, tp, ap, NULL); + np->sym = sym; + return np; + +error: + return constnode(zero); +} + +static Node * +builtin_va_copy(Symbol *sym) +{ + Node *np, *src, *dst; + + dst = assign(); + expect(','); + src = assign(); + + if (!valid_va_list(dst->type) || !valid_va_list(src->type)) { + errorp("incorrect parameters for va_copy"); + return constnode(zero); + } + + np = node(OBUILTIN, voidtype, dst, src); + np->sym = sym; + return np; +} + +static Node * +builtin_va_start(Symbol *sym) +{ + Node *np, *ap, *last; + Symbol **p; + Type *tp; + + ap = assign(); + expect(','); + last = assign(); + if (last->op != OSYM) + goto error; + + if (!valid_va_list(ap->type) || !(last->sym->flags&SDECLARED)) + goto error; + + for (p = curfun->u.pars; p && *p != last->sym; ++p) + ; + if (!p || *p == NULL || p[1] == NULL || p[1]->type != ellipsistype) + warn("second parameter of 'va_start' not last named argument"); + + tp = last->type; + if (tp == booltype || + tp == chartype || tp == uchartype || tp == schartype || + tp == shortype || tp == ushortype) { + warn("last parameter before '...' must not be bool, char or short"); + } + + np = node(OBUILTIN, voidtype, ap, last); + np->sym = sym; + return np; + +error: + errorp("incorrect parameters for va_start"); + return constnode(zero); +} + +static Node * +builtin_va_end(Symbol *sym) +{ + Node *ap, *np; + + ap = assign(); + + if (!valid_va_list(ap->type)) { + errorp("incorrect parameters for va_end"); + return constnode(zero); + } + + np = node(OBUILTIN, voidtype, ap, NULL); + np->sym = sym; + return np; +} + +void +ibuilts(void) +{ + struct builtin built[] = { + {"__builtin_va_arg", builtin_va_arg}, + {"__builtin_va_copy", builtin_va_copy}, + {"__builtin_va_start", builtin_va_start}, + {"__builtin_va_end", builtin_va_end}, + {NULL} + }; + builtins(built); +} diff --git a/cc1/cc1.h b/src/cc1/cc1.h diff --git a/src/cc1/code.c b/src/cc1/code.c @@ -0,0 +1,550 @@ +static char sccsid[] = "@(#) ./cc1/code.c"; +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> + +#include <scc/scc.h> +#include "cc1.h" + +static void emitbin(int, void *), + emitcast(int, void *), + emitsym(int, void *), + emitexp(int, void *), + emitsymid(int, void *), + emittext(int, void *), + emitfun(int, void *), + emitdcl(int, void *), + emitinit(int, void *), + emittype(int, void *), + emitbuilt(int, void *); + +char *optxt[] = { + [OADD] = "+", + [OSUB] = "-", + [OMUL] = "*", + [OINC] = ":i", + [ODEC] = ":d", + [OPTR] = "@", + [OMOD] = "%", + [ODIV] = "/", + [OSHL] = "l", + [OSHR] = "r", + [OLT] = "<", + [OGT] = ">", + [OGE] = "]", + [OLE] = "[", + [OEQ] = "=", + [ONE] = "!", + [OBAND] = "&", + [OBXOR] = "^", + [OBOR] = "|", + [OASSIGN] = ":", + [OA_MUL] = ":*", + [OA_DIV] = ":/", + [OA_MOD] = ":%", + [OA_ADD] = ":+", + [OA_SUB] = ":-", + [OA_SHL] = ":l", + [OA_SHR] = ":r", + [OA_AND] = ":&", + [OA_XOR] = ":^", + [OA_OR] = ":|", + [OADDR] = "'", + [OSNEG] = "_", + [ONEG] = "n", + [OCPL] = "~", + [OAND] = "a", + [OOR] = "o", + [OASK] = "?", + [OCOMMA] = ",", + [OLABEL] = "L%d\n", + [ODEFAULT] = "\tf\tL%d\n", + [OBSWITCH] = "\ts", + [OESWITCH] = "\tt\tL%d\n", + [OCASE] = "\tv\tL%d", + [OJUMP] = "\tj\tL%d\n", + [OBRANCH] = "\ty\tL%d", + [OEFUN] = "}\n", + [OELOOP] = "\tb\n", + [OBLOOP] = "\te\n", + [ORET] = "\th", + [OPAR] = "p", + [OCALL] = "c", + [OCALLE] = "z", + [OFIELD] = "." +}; + +void (*opcode[])(int, void *) = { + [OADD] = emitbin, + [OSUB] = emitbin, + [OMUL] = emitbin, + [OINC] = emitbin, + [ODEC] = emitbin, + [OPTR] = emitbin, + [OMOD] = emitbin, + [ODIV] = emitbin, + [OSHL] = emitbin, + [OSHR] = emitbin, + [OLT] = emitbin, + [OGT] = emitbin, + [OGE] = emitbin, + [OLE] = emitbin, + [OEQ] = emitbin, + [ONE] = emitbin, + [OBAND] = emitbin, + [OBXOR] = emitbin, + [OBOR] = emitbin, + [OASSIGN] = emitbin, + [OA_MUL] = emitbin, + [OA_DIV] = emitbin, + [OA_MOD] = emitbin, + [OA_ADD] = emitbin, + [OA_SUB] = emitbin, + [OA_SHL] = emitbin, + [OA_SHR] = emitbin, + [OA_AND] = emitbin, + [OA_XOR] = emitbin, + [OA_OR] = emitbin, + [OADDR] = emitbin, + [OSNEG] = emitbin, + [ONEG] = emitbin, + [OCPL] = emitbin, + [OAND] = emitbin, + [OOR] = emitbin, + [OCOMMA] = emitbin, + [OCAST] = emitcast, + [OSYM] = emitsym, + [OASK] = emitbin, + [OCOLON] = emitbin, + [OFIELD]= emitbin, + [OEXPR] = emitexp, + [OLABEL] = emitsymid, + [ODEFAULT] = emitsymid, + [OCASE] = emitsymid, + [OJUMP] = emitsymid, + [OBRANCH] = emitsymid, + [OEFUN] = emittext, + [OELOOP] = emittext, + [OBLOOP] = emittext, + [OFUN] = emitfun, + [ORET] = emittext, + [ODECL] = emitdcl, + [OBSWITCH] = emittext, + [OESWITCH] = emitsymid, + [OPAR] = emitbin, + [OCALL] = emitbin, + [OCALLE] = emitbin, + [OINIT] = emitinit, + [OBUILTIN] = emitbuilt, + [OTYP] = emittype, +}; + +static FILE *outfp; + +void +icode(void) +{ + outfp = stdout; +} + +void +freetree(Node *np) +{ + if (!np) + return; + freetree(np->left); + freetree(np->right); + free(np); +} + +static void +emitnode(Node *np) +{ + if (np) + (*opcode[np->op])(np->op, np); +} + +void +prtree(Node *np) +{ + outfp = stderr; + fputs("DBG prtree", outfp); + emitnode(np); + putc('\n', outfp); + outfp = stdout; +} + +void +emit(int op, void *arg) +{ + extern int failure; + + if (failure || onlycpp || onlyheader) + return; + (*opcode[op])(op, arg); +} + +static void +emitvar(Symbol *sym) +{ + int c; + short flags = sym->flags; + + if (flags & SLOCAL) + c = 'T'; + else if (flags & SPRIVATE) + c = 'Y'; + else if (flags & SGLOBAL) + c = 'G'; + else if (flags & SREGISTER) + c = 'R'; + else if (flags & SFIELD) + c = 'M'; + else if (flags & SEXTERN) + c = 'X'; + else + c = 'A'; + fprintf(outfp, "%c%u", c, sym->id); +} + +static void +emitconst(Node *np) +{ + Symbol *sym = np->sym; + Type *tp = np->type; + TUINT u; + + switch (tp->op) { + case PTR: + case INT: + case ENUM: + u = (tp->prop & TSIGNED) ? (TUINT) sym->u.i : sym->u.u; + fprintf(outfp, + "#%c%llX", + np->type->letter, + (long long) u & ones(tp->size)); + break; + default: + abort(); + } +} + +static void +emitsym(int op, void *arg) +{ + Node *np = arg; + + if ((np->sym->flags & SINITLST) == 0) { + /* + * When we have a compound literal we are going + * to call to emitnode for every element of it, + * and it means that we will have two '\t' + * for the first element + */ + putc('\t', outfp); + } + (np->flags & NCONST) ? emitconst(np) : emitvar(np->sym); +} + +static void +emitletter(Type *tp) +{ + int letter; + + letter = (tp->prop&TELLIPSIS) ? 'E' : tp->letter; + putc(letter, outfp); + switch (tp->op) { + case ARY: + case STRUCT: + case UNION: + fprintf(outfp, "%u", tp->id); + } +} + +static void +emittype(int op, void *arg) +{ + TINT n; + Symbol **sp; + char *tag; + Type *tp = arg; + + if (!(tp->prop & TDEFINED)) + return; + + switch (tp->op) { + case ARY: + emitletter(tp); + putc('\t', outfp); + emitletter(tp->type); + fprintf(outfp, + "\t#%c%llX\n", + sizettype->letter, (long long) tp->n.elem); + return; + case UNION: + case STRUCT: + emitletter(tp); + tag = tp->tag->name; + fprintf(outfp, + "\t\"%s\t#%c%lX\t#%c%X\n", + (tag) ? tag : "", + sizettype->letter, + tp->size, + sizettype->letter, + tp->align); + n = tp->n.elem; + for (sp = tp->p.fields; n-- > 0; ++sp) + emit(ODECL, *sp); + break; + case PTR: + case FTN: + case ENUM: + return; + default: + abort(); + } +} + +static void +emitstring(Symbol *sym, Type *tp) +{ + char *bp, *s, *lim; + int n; + + bp = sym->u.s; + lim = &sym->u.s[tp->n.elem]; + while (bp < lim) { + s = bp; + while (bp < lim && isprint(*bp)) + ++bp; + if ((n = bp - s) > 1) + fprintf(outfp, "\t#\"%.*s\n", n, s); + else + bp = s; + if (bp == lim) + break; + do { + fprintf(outfp, + "\t#%c%02X\n", + chartype->letter, (*bp++) & 0xFF); + } while (bp < lim && !isprint(*bp)); + } +} + +static void +emitdesig(Node *np, Type *tp) +{ + Symbol *sym; + size_t n; /* TODO: This should be SIZET */ + Node *aux; + Type *p; + + if (!np) { + sym = NULL; + } else { + if (!np->sym) + goto emit_expression; + sym = np->sym; + if (sym->flags & SSTRING) { + emitstring(sym, tp); + return; + } + if ((sym->flags & SINITLST) == 0) + goto emit_expression; + } + + switch (tp->op) { + case PTR: + case INT: + case ENUM: + aux = (sym) ? *sym->u.init : convert(constnode(zero), tp, 0); + emitexp(OEXPR, aux); + break; + case UNION: + n = tp->n.elem-1; + aux = (sym) ? sym->u.init[0] : NULL; + emitdesig(aux, aux->type); + break; + case STRUCT: + case ARY: + for (n = 0; n < tp->n.elem; ++n) { + aux = (sym) ? sym->u.init[n] : NULL; + p = (tp->op == ARY) ? tp->type : tp->p.fields[n]->type; + emitdesig(aux, p); + } + break; + default: + abort(); + } + + if (sym) { + free(sym->u.init); + sym->u.init = NULL; + } + freetree(np); + return; + +emit_expression: + emitexp(OEXPR, np); +} + +static void +emitinit(int op, void *arg) +{ + Node *np = arg; + + fputs("\t(\n", outfp); + emitdesig(np, np->type); + fputs(")\n", outfp); +} + +static void +emitdcl(int op, void *arg) +{ + Symbol *sym = arg; + + if (sym->flags & SEMITTED) + return; + emitvar(sym); + putc('\t', outfp); + if (sym->type->op == FTN) { + emitletter(sym->type->type); + putc('\t', outfp); + } + emitletter(sym->type); + fprintf(outfp, "\t\"%s", (sym->name) ? sym->name : ""); + if (sym->flags & SFIELD) + fprintf(outfp, "\t#%c%llX", sizettype->letter, sym->u.i); + sym->flags |= SEMITTED; + if ((sym->flags & SHASINIT) == 0) + putc('\n', outfp); +} + +static void +emitcast(int op, void *arg) +{ + Node *np = arg, *lp = np->left; + + emitnode(lp); + if (np->type != voidtype) + fprintf(outfp, "\tg%c", np->type->letter); +} + +static void +emitbin(int op, void *arg) +{ + Node *np = arg; + char *s; + + emitnode(np->left); + emitnode(np->right); + if ((s = optxt[op]) != NULL) { /* do not print in OCOLON case */ + fprintf(outfp, "\t%s", s); + emitletter(np->type); + } +} + +static void +emitbuilt(int op, void *arg) +{ + Node *np = arg; + + emitnode(np->left); + emitnode(np->right); + fprintf(outfp, "\t\"%s\tm", np->sym->name); + emitletter(np->type); +} + + +static void +emitexp(int op, void *arg) +{ + Node *np = arg; + + emitnode(np); + putc('\n', outfp); + freetree(np); +} + +static void +emitfun(int op, void *arg) +{ + Symbol *sym = arg, **sp; + + emitdcl(op, arg); + fputs("{\n", outfp); + + for (sp = sym->u.pars; sp && *sp; ++sp) + emit(ODECL, *sp); + fputs("\\\n", outfp); +} + +static void +emittext(int op, void *arg) +{ + fputs(optxt[op], outfp); +} + +static void +emitsymid(int op, void *arg) +{ + Symbol *sym = arg; + fprintf(outfp, optxt[op], sym->id); +} + +Node * +node(int op, Type *tp, Node *lp, Node *rp) +{ + Node *np; + + np = xmalloc(sizeof(*np)); + np->op = op; + np->type = tp; + np->sym = NULL; + np->flags = 0; + np->left = lp; + np->right = rp; + + if (lp) + np->flags |= lp->flags & NEFFECT; + if (rp) + np->flags |= rp->flags & NEFFECT; + return np; +} + +Node * +varnode(Symbol *sym) +{ + Node *np; + Type *tp = sym->type; + + np = node(OSYM, sym->type, NULL, NULL); + np->type = sym->type; + np->flags = (tp->op != FTN && tp->op != ARY) ? NLVAL : 0; + np->sym = sym; + return np; +} + +Node * +constnode(Symbol *sym) +{ + Node *np; + + np = node(OSYM, sym->type, NULL, NULL); + np->type = sym->type; + np->flags = NCONST; + np->sym = sym; + return np; +} + +Node * +sizeofnode(Type *tp) +{ + Symbol *sym; + + sym = newsym(NS_IDEN, NULL); + sym->type = sizettype; + sym->u.i = tp->size; + return constnode(sym); +} diff --git a/src/cc1/cpp.c b/src/cc1/cpp.c @@ -0,0 +1,839 @@ +static char sccsid[] = "@(#) ./cc1/cpp.c"; +#include <ctype.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> + +#include <scc/cstd.h> +#include <scc/scc.h> +#include "cc1.h" + +static char *argp, *macroname; +static unsigned arglen; +static unsigned ncmdlines; +static Symbol *symline, *symfile; +static unsigned char ifstatus[NR_COND]; +static int cppoff; +static struct items dirinclude; + +unsigned cppctx; +int disexpand; + +void +defdefine(char *macro, char *val, char *source) +{ + char *def, *fmt = "#define %s %s\n"; + Symbol dummy = {.flags = SDECLARED}; + + if (!val) + val = ""; + def = xmalloc(strlen(fmt) + strlen(macro) + strlen(val)); + + sprintf(def, fmt, macro, val); + lineno = ++ncmdlines; + addinput(source, &dummy, def); + cpp(); + delinput(); +} + +void +undefmacro(char *s) +{ + killsym(lookup(NS_CPP, s, NOALLOC)); +} + +void +icpp(void) +{ + static char sdate[14], stime[11]; + struct tm *tm; + time_t t; + static char **bp, *list[] = { + "__STDC__", + "__STDC_HOSTED__", + "__SCC__", + NULL + }; + static struct keyword keys[] = { + {"define", DEFINE, DEFINE}, + {"include", INCLUDE, INCLUDE}, + {"line", LINE, LINE}, + {"ifdef", IFDEF, IFDEF}, + {"if", IF, IF}, + {"elif", ELIF, ELIF}, + {"else", ELSE, ELSE}, + {"ifndef", IFNDEF, IFNDEF}, + {"endif", ENDIF, ENDIF}, + {"undef", UNDEF, UNDEF}, + {"pragma", PRAGMA, PRAGMA}, + {"error", ERROR, ERROR}, + {NULL, 0, 0} + }; + + keywords(keys, NS_CPPCLAUSES); + + t = time(NULL); + tm = localtime(&t); + strftime(sdate, sizeof(sdate), "\"%b %d %Y\"", tm); + strftime(stime, sizeof(stime), "\"%H:%M:%S\"", tm); + defdefine("__DATE__", sdate, "built-in"); + defdefine("__TIME__", stime, "built-in"); + defdefine("__STDC_VERSION__", STDC_VERSION, "built-in"); + defdefine("__LINE__", NULL, "built-in"); + defdefine("__FILE__", NULL, "built-in"); + + symline = lookup(NS_CPP, "__LINE__", ALLOC); + symfile = lookup(NS_CPP, "__FILE__", ALLOC); + + for (bp = list; *bp; ++bp) + defdefine(*bp, "1", "built-in"); + + ncmdlines = 0; +} + +static void +nextcpp(void) +{ + next(); + if (yytoken == EOFTOK) + error("unterminated argument list invoking macro \"%s\"", + macroname); + if (yylen + 1 > arglen) + error("argument overflow invoking macro \"%s\"", + macroname); + if (yytoken == IDEN) + yylval.sym->flags |= SUSED; + memcpy(argp, yytext, yylen); + argp += yylen; + *argp++ = ' '; + arglen -= yylen + 1; +} + +static void +paren(void) +{ + for (;;) { + nextcpp(); + switch (yytoken) { + case ')': + return; + case '(': + paren(); + break; + } + } +} + +static void +parameter(void) +{ + for (;;) { + nextcpp(); + switch (yytoken) { + case ')': + case ',': + argp -= 3; /* remove " , " or " ) "*/ + *argp++ = '\0'; + return; + case '(': + paren(); + break; + } + } +} + +static int +parsepars(char *buffer, char **listp, int nargs) +{ + int n; + + if (nargs == -1) + return -1; + if (ahead() != '(' && nargs > 0) + return 0; + + disexpand = 1; + next(); + n = 0; + argp = buffer; + arglen = INPUTSIZ; + if (ahead() == ')') { + next(); + } else { + do { + *listp++ = argp; + parameter(); + } while (++n < NR_MACROARG && yytoken == ','); + } + if (yytoken != ')') + error("incorrect macro function-alike invocation"); + disexpand = 0; + + if (n == NR_MACROARG) + error("too many parameters in macro \"%s\"", macroname); + if (n != nargs) { + error("macro \"%s\" received %d arguments, but it takes %d", + macroname, n, nargs); + } + + return 1; +} + +static size_t +copymacro(char *buffer, char *s, size_t bufsiz, char *arglist[]) +{ + int delim, prevc, c; + char *p, *arg, *bp = buffer; + size_t size; + + for (prevc = '\0'; c = *s; prevc = c, ++s) { + switch (c) { + case '$': + while (bp[-1] == ' ') + --bp, ++bufsiz; + while (s[1] == ' ') + ++s; + case '#': + break; + case '\'': + delim = '\''; + goto search_delim; + case '\"': + delim = '"'; + search_delim: + for (p = s; *++s != delim; ) + ; + size = s - p + 1; + if (size > bufsiz) + goto expansion_too_long; + memcpy(bp, p, size); + bufsiz -= size; + bp += size; + break; + case '@': + if (prevc == '#') + bufsiz -= 2; + arg = arglist[atoi(++s)]; + size = strlen(arg); + if (size > bufsiz) + goto expansion_too_long; + if (prevc == '#') + *bp++ = '"'; + memcpy(bp, arg, size); + bp += size; + if (prevc == '#') + *bp++ = '"'; + bufsiz -= size; + s += 2; + break; + default: + if (bufsiz-- == 0) + goto expansion_too_long; + *bp++ = c; + break; + } + } + *bp = '\0'; + + return bp - buffer; + +expansion_too_long: + error("macro expansion of \"%s\" too long", macroname); +} + +int +expand(char *begin, Symbol *sym) +{ + size_t elen; + int n, i; + char *s = sym->u.s; + char *arglist[NR_MACROARG], arguments[INPUTSIZ], buffer[INPUTSIZ]; + + macroname = sym->name; + if (sym == symfile) { + elen = sprintf(buffer, "\"%s\" ", filenam); + goto substitute; + } + if (sym == symline) { + elen = sprintf(buffer, "%d ", lineno); + goto substitute; + } + if (!s) + return 1; + + n = atoi(s); + if (!parsepars(arguments, arglist, atoi(s))) + return 0; + for (i = 0; i < n; ++i) + DBG("MACRO par%d:%s", i, arglist[i]); + + elen = copymacro(buffer, s+3, INPUTSIZ-1, arglist); + +substitute: + DBG("MACRO '%s' expanded to :'%s'", macroname, buffer); + buffer[elen] = '\0'; + addinput(filenam, sym, xstrdup(buffer)); + + return 1; +} + +static int +getpars(Symbol *args[NR_MACROARG]) +{ + int n, c; + Symbol *sym; + + c = *input->p; + next(); + if (c != '(') + return -1; + next(); /* skip the '(' */ + if (accept(')')) + return 0; + + n = 0; + do { + if (n == NR_MACROARG) { + cpperror("too many parameters in macro"); + return NR_MACROARG; + } + if (accept(ELLIPSIS)) { + args[n++] = NULL; + break; + } + if (yytoken != IDEN) { + cpperror("macro arguments must be identifiers"); + return NR_MACROARG; + } + sym = install(NS_IDEN, yylval.sym); + sym->flags |= SUSED; + args[n++] = sym; + next(); + } while (accept(',')); + expect(')'); + + return n; +} + +static int +getdefs(Symbol *args[NR_MACROARG], int nargs, char *bp, size_t bufsiz) +{ + Symbol **argp; + size_t len; + int prevc = 0, ispar; + + if (yytoken == '$') { + cpperror("'##' cannot appear at either ends of a macro expansion"); + return 0; + } + + for (;;) { + ispar = 0; + if (yytoken == IDEN && nargs >= 0) { + for (argp = args; argp < &args[nargs]; ++argp) { + if (*argp == yylval.sym) + break; + } + if (argp != &args[nargs]) { + sprintf(yytext, "@%02d@", (int) (argp - args)); + ispar = 1; + } + } + if (prevc == '#' && !ispar) { + cpperror("'#' is not followed by a macro parameter"); + return 0; + } + if (yytoken == '\n') + break; + + if ((len = strlen(yytext)) >= bufsiz) { + cpperror("macro too long"); + return 0; + } + if (yytoken == '$') { + *bp++ = '$'; + --bufsiz; + } else { + memcpy(bp, yytext, len); + bp += len; + bufsiz -= len; + } + if ((prevc = yytoken) != '#') { + *bp++ = ' '; + --bufsiz; + } + next(); + } + *bp = '\0'; + return 1; +} + +static void +define(void) +{ + Symbol *sym,*args[NR_MACROARG]; + char buff[LINESIZ+1]; + int n; + + if (cppoff) + return; + + namespace = NS_CPP; + next(); + + if (yytoken != IDEN) { + cpperror("macro names must be identifiers"); + return; + } + sym = yylval.sym; + if (sym->flags & SDECLARED) { + warn("'%s' redefined", yytext); + free(sym->u.s); + } else { + sym = install(NS_CPP, sym); + sym->flags |= SDECLARED|SSTRING; + } + + namespace = NS_IDEN; /* Avoid polution in NS_CPP */ + if ((n = getpars(args)) == NR_MACROARG) + goto delete; + if (n > 0 && !args[n-1]) /* it is a variadic function */ + --n; + sprintf(buff, "%02d#", n); + if (!getdefs(args, n, buff+3, LINESIZ-3)) + goto delete; + sym->u.s = xstrdup(buff); + DBG("MACRO '%s' defined as '%s'", sym->name, buff); + return; + +delete: + killsym(sym); +} + +void +incdir(char *dir) +{ + if (!dir || *dir == '\0') + die("cc1: incorrect -I flag"); + newitem(&dirinclude, dir); +} + +static int +includefile(char *dir, char *file, size_t filelen) +{ + size_t dirlen; + char path[FILENAME_MAX]; + + if (!dir) { + dirlen = 0; + if (filelen > FILENAME_MAX-1) + return 0; + } else { + dirlen = strlen(dir); + if (dirlen + filelen > FILENAME_MAX-2) + return 0; + memcpy(path, dir, dirlen); + if (dir[dirlen-1] != '/') + path[dirlen++] = '/'; + } + memcpy(path+dirlen, file, filelen); + path[dirlen + filelen] = '\0'; + + addinput(path, NULL, NULL); + return 1; +} + +static char * +cwd(char *buf) +{ + char *p, *s = filenam; + size_t len; + + if ((p = strrchr(s, '/')) == NULL) + return NULL; + if ((len = p - s) >= FILENAME_MAX) + die("cc1: current work directory too long"); + memcpy(buf, s, len); + buf[len] = '\0'; + return buf; +} + +static void +include(void) +{ + char dir[FILENAME_MAX], file[FILENAME_MAX], *p, **bp; + size_t filelen; + int n; + + if (cppoff) + return; + + namespace = NS_IDEN; + next(); + + switch (*yytext) { + case '<': + if ((p = strchr(input->begin, '>')) == NULL || p[-1] == '<') + goto bad_include; + filelen = p - input->begin; + if (filelen >= FILENAME_MAX) + goto too_long; + memcpy(file, input->begin, filelen); + file[filelen] = '\0'; + + input->begin = input->p = p+1; + if (next() != '\n') + goto trailing_characters; + + break; + case '"': + if (yylen < 3) + goto bad_include; + filelen = yylen-2; + if (filelen >= FILENAME_MAX) + goto too_long; + memcpy(file, yytext+1, filelen); + file[filelen] = '\0'; + + if (next() != '\n') + goto trailing_characters; + + if (includefile(cwd(dir), file, filelen)) + goto its_done; + break; + default: + goto bad_include; + } + + n = dirinclude.n; + for (bp = dirinclude.s; n--; ++bp) { + if (includefile(*bp, file, filelen)) + goto its_done; + } + cpperror("included file '%s' not found", file); + +its_done: + return; + +trailing_characters: + cpperror("trailing characters after preprocessor directive"); + return; + +too_long: + cpperror("too long file name in #include"); + return; + +bad_include: + cpperror("#include expects \"FILENAME\" or <FILENAME>"); + return; +} + +static void +line(void) +{ + long n; + char *endp, *fname; + + if (cppoff) + return; + + disexpand = 0; + next(); + n = strtol(yytext, &endp, 10); + if (n <= 0 || n > USHRT_MAX || *endp != '\0') { + cpperror("first parameter of #line is not a positive integer"); + return; + } + + next(); + if (yytoken == '\n') { + fname = NULL; + } else { + if (*yytext != '\"' || yylen == 1) { + cpperror("second parameter of #line is not a valid filename"); + return; + } + fname = yylval.sym->u.s; + } + setloc(fname, n - 1); + if (yytoken != '\n') + next(); +} + +static void +pragma(void) +{ + if (cppoff) + return; + next(); + warn("ignoring pragma '%s'", yytext); + *input->p = '\0'; + next(); +} + +static void +usererr(void) +{ + if (cppoff) + return; + cpperror("#error %s", input->p); + *input->p = '\0'; + next(); +} + +static void +ifclause(int negate, int isifdef) +{ + Symbol *sym; + unsigned n; + int status; + Node *expr; + + if (cppctx == NR_COND-1) + error("too many nesting levels of conditional inclusion"); + + n = cppctx++; + namespace = NS_CPP; + next(); + + if (isifdef) { + if (yytoken != IDEN) { + cpperror("no macro name given in #%s directive", + (negate) ? "ifndef" : "ifdef"); + return; + } + sym = yylval.sym; + next(); + status = (sym->flags & SDECLARED) != 0; + if (!status) + killsym(sym); + } else { + /* TODO: catch recovery here */ + if ((expr = constexpr()) == NULL) { + cpperror("parameter of #if is not an integer constant expression"); + return; + } + status = expr->sym->u.i != 0; + freetree(expr); + } + + if (negate) + status = !status; + if ((ifstatus[n] = status) == 0) + ++cppoff; +} + +static void +cppif(void) +{ + disexpand = 0; + ifclause(0, 0); +} + +static void +ifdef(void) +{ + ifclause(0, 1); +} + +static void +ifndef(void) +{ + ifclause(1, 1); +} + +static void +elseclause(void) +{ + int status; + + if (cppctx == 0) { + cpperror("#else without #ifdef/ifndef"); + return; + } + + status = ifstatus[cppctx-1]; + ifstatus[cppctx-1] = !status; + cppoff += (status) ? 1 : -1; +} + +static void +cppelse(void) +{ + elseclause(); + next(); +} + +static void +elif(void) +{ + elseclause(); + if (ifstatus[cppctx-1]) { + --cppctx; + cppif(); + } +} + +static void +endif(void) +{ + if (cppctx == 0) + error("#endif without #if"); + if (!ifstatus[--cppctx]) + --cppoff; + next(); +} + +static void +undef(void) +{ + if (cppoff) + return; + + namespace = NS_CPP; + next(); + if (yytoken != IDEN) { + error("no macro name given in #undef directive"); + return; + } + killsym(yylval.sym); + next(); +} + +int +cpp(void) +{ + static struct { + unsigned char token; + void (*fun)(void); + } *bp, clauses [] = { + {DEFINE, define}, + {INCLUDE, include}, + {LINE, line}, + {IFDEF, ifdef}, + {IF, cppif}, + {ELIF, elif}, + {IFNDEF, ifndef}, + {ELSE, cppelse}, + {ENDIF, endif}, + {UNDEF, undef}, + {PRAGMA, pragma}, + {ERROR, usererr}, + {0, NULL} + }; + int ns; + char *p; + + for (p = input->p; isspace(*p); ++p) + ; + + if (*p != '#') + return cppoff; + input->p = p+1; + + disexpand = 1; + lexmode = CPPMODE; + ns = namespace; + namespace = NS_CPPCLAUSES; + next(); + namespace = NS_IDEN; + + for (bp = clauses; bp->token && bp->token != yytoken; ++bp) + ; + if (!bp->token) { + errorp("incorrect preprocessor directive '%s'", yytext); + goto error; + } + + DBG("CPP %s", yytext); + + pushctx(); /* create a new context to avoid polish */ + (*bp->fun)(); /* the current context, and to get all */ + popctx(); /* the symbols freed at the end */ + + /* + * #include changes the content of input->line, so the correctness + * of the line must be checked in the own include(), and we have + * to skip this tests. For the same reason include() is the only + * function which does not prepare the next token + */ + if (yytoken != '\n' && !cppoff && bp->token != INCLUDE) + errorp("trailing characters after preprocessor directive"); + +error: + disexpand = 0; + lexmode = CCMODE; + namespace = ns; + + return 1; +} + +void +ppragmaln(void) +{ + static char file[FILENAME_MAX]; + static unsigned nline; + char *s; + + putchar('\n'); + if (strcmp(file, filenam)) { + strcpy(file, filenam); + s = "#line %u \"%s\"\n"; + } else if (nline+1 != lineno) { + s = "#line %u\n"; + } else { + s = ""; + } + nline = lineno; + printf(s, nline, file); +} + +void +outcpp(void) +{ + int c; + char *s, *t; + + for (next(); yytoken != EOFTOK; next()) { + if (onlyheader) + continue; + if (yytoken != STRING) { + printf("%s ", yytext); + continue; + } + for (s = yytext; c = *s; ++s) { + switch (c) { + case '\n': + t = "\\n"; + goto print_str; + case '\v': + t = "\\v"; + goto print_str; + case '\b': + t = "\\b"; + goto print_str; + case '\t': + t = "\\t"; + goto print_str; + case '\a': + t = "\\a"; + print_str: + fputs(t, stdout); + break; + case '\\': + putchar('\\'); + default: + if (!isprint(c)) + printf("\\x%x", c); + else + putchar(c); + break; + } + } + putchar(' '); + } + putchar('\n'); +} + diff --git a/src/cc1/decl.c b/src/cc1/decl.c @@ -0,0 +1,967 @@ +static char sccsid[] = "@(#) ./cc1/decl.c"; +#include <stdarg.h> +#include <stdlib.h> +#include <string.h> + +#include <scc/cstd.h> +#include <scc/scc.h> +#include "cc1.h" + +#define NOSCLASS 0 + +#define NOREP 0 +#define REP 1 +#define QUIET 1 +#define NOQUIET 0 + +#define NR_DCL_TYP (NR_DECLARATORS+NR_FUNPARAM) +#define NR_DCL_SYM (NR_DECLARATORS+NR_FUNPARAM+1) + +struct declarators { + unsigned nr; + unsigned ns; + struct decl *dcl; + unsigned nr_types; + Type **tpars; + Symbol **pars; + struct declarator { + unsigned char op; + TINT nelem; + Symbol *sym; + Type **tpars; + Symbol **pars; + } d [NR_DECLARATORS]; +}; + +struct decl { + unsigned ns; + int sclass; + int qualifier; + Symbol *sym; + Type *type; + Type *parent; + Symbol **pars; + Symbol *bufpars[NR_DCL_SYM]; + Type *buftpars[NR_DCL_TYP]; +}; + + +static void +endfundcl(Type *tp, Symbol **pars) +{ + if (tp->prop&TK_R && *pars) + warn("parameter names (without types) in function declaration"); + /* + * avoid non used warnings in prototypes + */ + while (*pars) + (*pars++)->flags |= SUSED; + popctx(); +} + +static void +push(struct declarators *dp, int op, ...) +{ + va_list va; + unsigned n; + struct declarator *p; + + va_start(va, op); + if ((n = dp->nr++) == NR_DECLARATORS) + error("too many declarators"); + + p = &dp->d[n]; + p->op = op; + p->tpars = NULL; + + switch (op) { + case ARY: + p->nelem = va_arg(va, TINT); + break; + case KRFTN: + case FTN: + p->nelem = va_arg(va, unsigned); + p->tpars = va_arg(va, Type **); + p->pars = va_arg(va, Symbol **); + break; + case IDEN: + p->sym = va_arg(va, Symbol *); + break; + } + va_end(va); +} + +static int +pop(struct declarators *dp, struct decl *dcl) +{ + struct declarator *p; + + if (dp->nr == 0) + return 0; + + p = &dp->d[--dp->nr]; + if (p->op == IDEN) { + dcl->sym = p->sym; + return 1; + } + + if (dcl->type->op == FTN) + endfundcl(dcl->type, dcl->pars); + dcl->pars = p->pars; + + dcl->type = mktype(dcl->type, p->op, p->nelem, p->tpars); + return 1; +} + +static void +arydcl(struct declarators *dp) +{ + Node *np = NULL; + TINT n = 0; + + expect('['); + if (yytoken != ']') { + if ((np = constexpr()) == NULL) { + errorp("invalid storage size"); + } else { + if ((n = np->sym->u.i) <= 0) { + errorp("array size is not a positive number"); + n = 1; + } + freetree(np); + } + } + expect(']'); + + push(dp, ARY, n); +} + +static int +empty(Symbol *sym, Type *tp, int param) +{ + if (!sym->name) { + sym->type = tp; + switch (tp->op) { + default: + /* warn if it is not a parameter */ + if (!param) + warn("empty declaration"); + case STRUCT: + case UNION: + case ENUM: + return 1; + } + } + return 0; +} + +static void +bad_storage(Type *tp, char *name) +{ + if (tp->op != FTN) + errorp("incorrect storage class for file-scope declaration"); + else + errorp("invalid storage class for function '%s'", name); +} + +static Symbol * +redcl(Symbol *sym, Type *tp, int sclass) +{ + int flags; + char *name = sym->name; + + if (!eqtype(sym->type, tp, 1)) { + errorp("conflicting types for '%s'", name); + return sym; + } + + if (sym->token == TYPEIDEN && sclass != TYPEDEF || + sym->token != TYPEIDEN && sclass == TYPEDEF) { + goto redeclaration; + } + if (curctx != GLOBALCTX && tp->op != FTN) { + /* is it the redeclaration of a local variable? */ + if ((sym->flags & SEXTERN) && sclass == EXTERN) + return sym; + goto redeclaration; + } + + flags = sym->flags; + switch (sclass) { + case REGISTER: + case AUTO: + bad_storage(tp, name); + break; + case NOSCLASS: + if ((flags & SPRIVATE) == 0) { + if (flags & SEXTERN) + flags &= ~(SEXTERN|SEMITTED); + flags |= SGLOBAL; + break; + } + errorp("non-static declaration of '%s' follows static declaration", + name); + break; + case TYPEDEF: + /* Only C11 allows multiple definitions of a typedef. */ + goto redeclaration; + case EXTERN: + break; + case STATIC: + if ((flags & (SGLOBAL|SEXTERN)) == 0) { + flags |= SPRIVATE; + break; + } + errorp("static declaration of '%s' follows non-static declaration", + name); + break; + } + sym->flags = flags; + + return sym; + +redeclaration: + errorp("redeclaration of '%s'", name); + return sym; +} + +static Symbol * +identifier(struct decl *dcl) +{ + Symbol *sym = dcl->sym; + Type *tp = dcl->type; + int sclass = dcl->sclass; + char *name = sym->name; + + if (empty(sym, tp, 0)) + return sym; + + /* TODO: Add warning about ANSI limits */ + if (!(tp->prop & TDEFINED) && + sclass != EXTERN && sclass != TYPEDEF && + !(tp->op == ARY && yytoken == '=')) { + errorp("declared variable '%s' of incomplete type", name); + } + + if (tp->op == FTN) { + if (sclass == NOSCLASS) + sclass = EXTERN; + if (!strcmp(name, "main") && tp->type != inttype) { + errorp("main shall be defined with a return type of int"); + errorp("please contact __20h__ on irc.freenode.net (#bitreich-en) via IRC"); + } + } + + if (sym->flags & SDECLARED) { + sym = redcl(dcl->sym, tp, sclass); + } else { + int flags = sym->flags | SDECLARED; + + sym->type = tp; + + switch (sclass) { + case REGISTER: + case AUTO: + if (curctx != GLOBALCTX && tp->op != FTN) { + flags |= (sclass == REGISTER) ? SREGISTER : SAUTO; + break; + } + bad_storage(tp, name); + case NOSCLASS: + if (tp->op == FTN) + flags |= SEXTERN; + else + flags |= (curctx == GLOBALCTX) ? SGLOBAL : SAUTO; + break; + case EXTERN: + flags |= SEXTERN; + break; + case STATIC: + flags |= (curctx == GLOBALCTX) ? SPRIVATE : SLOCAL; + break; + case TYPEDEF: + flags |= STYPEDEF; + sym->u.token = sym->token = TYPEIDEN; + break; + } + sym->flags = flags; + } + + if (accept('=')) + initializer(sym, sym->type); + if (!(sym->flags & (SGLOBAL|SEXTERN)) && tp->op != FTN) + sym->flags |= SDEFINED; + if (sym->token == IDEN && tp->op != FTN) + emit(ODECL, sym); + return sym; +} + +static Symbol * +parameter(struct decl *dcl) +{ + Symbol *sym = dcl->sym; + Type *funtp = dcl->parent, *tp = dcl->type; + char *name = sym->name; + int flags; + + flags = 0; + switch (dcl->sclass) { + case STATIC: + case EXTERN: + case AUTO: + errorp("bad storage class in function parameter"); + break; + case REGISTER: + flags |= SREGISTER; + break; + case NOSCLASS: + flags |= SAUTO; + break; + } + + switch (tp->op) { + case VOID: + funtp->n.elem = 1; + if (dcl->sclass) + errorp("void as unique parameter may not be qualified"); + return NULL; + case ARY: + tp = mktype(tp->type, PTR, 0, NULL); + break; + case FTN: + errorp("incorrect function type for a function parameter"); + return NULL; + } + if (!empty(sym, tp, 1)) { + int isdcl = sym->flags&SDECLARED, isk_r = funtp->prop & TK_R; + if (isdcl && !isk_r) { + errorp("redefinition of parameter '%s'", name); + return NULL; + } + if (!isdcl && isk_r) { + errorp("declaration for parameter '%s' but no such parameter", + sym->name); + return NULL; + } + sym->flags |= SDECLARED; + } + + sym->type = tp; + sym->flags &= ~(SAUTO|SREGISTER); + sym->flags |= flags; + return sym; +} + +static Symbol *dodcl(int rep, + Symbol *(*fun)(struct decl *), + unsigned ns, + Type *type); + +static int +krpars(struct declarators *dp) +{ + Symbol *sym; + int toomany = 0; + unsigned npars = 0; + + do { + sym = yylval.sym; + expect(IDEN); + sym->flags |= SAUTO; + if ((sym = install(NS_IDEN, sym)) == NULL) { + errorp("redefinition of parameter '%s'", + yylval.sym->name); + continue; + } + if (npars < NR_FUNPARAM) { + ++npars; + *dp->pars++ = sym; + continue; + } + if (!toomany) + toomany = 1; + } while (accept(',')); + + return toomany; +} + +static unsigned +krfun(struct declarators *dp) +{ + int toomany = 0; + + + if (yytoken != ')') + toomany = krpars(dp); + + if (dp->nr_types == NR_DCL_TYP) { + toomany = 1; + } else { + ++dp->nr_types; + *dp->tpars++ = ellipsistype; + } + + if (toomany) + errorp("too many parameters in function definition"); + return 1; +} + +static unsigned +ansifun(struct declarators *dp) +{ + Symbol *sym; + unsigned npars, ntype, toomany, distoomany, voidpar; + Type type, *tp; + + type.n.elem = 0; + type.prop = 0; + npars = ntype = toomany = distoomany = voidpar = 0; + + do { + if (accept(ELLIPSIS)) { + if (ntype < 1) + errorp("a named argument is requiered before '...'"); + if (yytoken != ')') + errorp("... must be the last parameter"); + sym = NULL; + tp = ellipsistype; + } else if ((sym = dodcl(NOREP, parameter, NS_IDEN, &type)) == NULL) { + if (type.n.elem == 1 && ntype > 1) + voidpar = 1; + sym = NULL; + tp = NULL; + } else { + tp = sym->type; + } + + if (sym) { + if (npars == NR_FUNPARAM) { + toomany = 1; + } else { + npars++; + *dp->pars++ = sym; + } + } + + if (tp) { + if (dp->nr_types == NR_DCL_TYP) { + toomany = 1; + } else { + ntype++; + dp->nr_types++; + *dp->tpars++ = tp; + } + } + + } while (accept(',')); + + if (toomany == 1) + errorp("too many parameters in function definition"); + if (voidpar && ntype > 1) + errorp("'void' must be the only parameter"); + return ntype; +} + +static int +funbody(Symbol *sym, Symbol *pars[]) +{ + Type *tp; + Symbol **bp, *p; + + if (!sym) + return 0; + tp = sym->type; + if (tp->op != FTN) + return 0; + + switch (yytoken) { + case '{': + case TYPE: + case TYPEIDEN: + if (curctx != PARAMCTX) + errorp("nested function declaration"); + if (sym && sym->ns == NS_IDEN) + break; + default: + emit(ODECL, sym); + endfundcl(tp, pars); + return 0; + } + + tp->prop |= TFUNDEF; + curfun = sym; + if (sym->type->prop & TK_R) { + while (yytoken != '{') { + dodcl(REP, parameter, NS_IDEN, sym->type); + expect(';'); + } + for (bp = pars; p = *bp; ++bp) { + if (p->type == NULL) { + warn("type of '%s' defaults to int", p->name); + p->type = inttype; + } + } + } + if (sym->flags & STYPEDEF) + errorp("function definition declared 'typedef'"); + if (sym->flags & SDEFINED) + errorp("redefinition of '%s'", sym->name); + if (sym->flags & SEXTERN) { + sym->flags &= ~SEXTERN; + sym->flags |= SGLOBAL; + } + sym->flags |= SDEFINED; + sym->flags &= ~SEMITTED; + sym->u.pars = pars; + emit(OFUN, sym); + compound(NULL, NULL, NULL); + emit(OEFUN, NULL); + popctx(); + flushtypes(); + curfun = NULL; + return 1; +} + +static void +fundcl(struct declarators *dp) +{ + Type **types = dp->tpars; + unsigned ntypes, typefun; + Symbol **pars = dp->pars; + unsigned (*fun)(struct declarators *); + + pushctx(); + expect('('); + if (yytoken == ')' || yytoken == IDEN) { + typefun = KRFTN; + fun = krfun; + } else { + typefun = FTN; + fun = ansifun; + } + ntypes = (*fun)(dp); + *dp->pars++= NULL; + expect(')'); + + push(dp, typefun, ntypes, types, pars); +} + +static void declarator(struct declarators *dp); + +static void +directdcl(struct declarators *dp) +{ + Symbol *p, *sym; + static int nested; + + if (accept('(')) { + if (nested == NR_SUBTYPE) + error("too many declarators nested by parentheses"); + ++nested; + declarator(dp); + --nested; + expect(')'); + } else { + if (yytoken == IDEN || yytoken == TYPEIDEN) { + sym = yylval.sym; + if (p = install(dp->ns, sym)) { + sym = p; + sym->flags &= ~SDECLARED; + } + next(); + } else { + sym = newsym(dp->ns, NULL); + } + push(dp, IDEN, sym); + } + + for (;;) { + switch (yytoken) { + case '(': fundcl(dp); break; + case '[': arydcl(dp); break; + default: return; + } + } +} + +static void +declarator(struct declarators *dp) +{ + unsigned n; + + for (n = 0; accept('*'); ++n) { + while (accept(TQUALIFIER)) + ; + } + + directdcl(dp); + + while (n--) + push(dp, PTR); +} + +static Type *structdcl(void), *enumdcl(void); + +static Type * +specifier(int *sclass, int *qualifier) +{ + Type *tp = NULL; + unsigned spec, qlf, sign, type, cls, size; + + spec = qlf = sign = type = cls = size = 0; + + for (;;) { + unsigned *p = NULL; + Type *(*dcl)(void) = NULL; + + switch (yytoken) { + case SCLASS: + p = &cls; + break; + case TQUALIFIER: + qlf |= yylval.token; + next(); + continue; + case TYPEIDEN: + if (type) + goto return_type; + tp = yylval.sym->type; + p = &type; + break; + case TYPE: + switch (yylval.token) { + case ENUM: + dcl = enumdcl; + p = &type; + break; + case STRUCT: + case UNION: + dcl = structdcl; + p = &type; + break; + case VA_LIST: + case VOID: + case BOOL: + case CHAR: + case INT: + case FLOAT: + case DOUBLE: + p = &type; + break; + case SIGNED: + case UNSIGNED: + p = &sign; + break; + case LONG: + if (size == LONG) { + yylval.token = LLONG; + size = 0; + } + case SHORT: + p = &size; + break; + } + break; + default: + goto return_type; + } + if (*p) + errorp("invalid type specification"); + *p = yylval.token; + if (dcl) { + if (size || sign) + errorp("invalid type specification"); + tp = (*dcl)(); + goto return_type; + } else { + next(); + } + spec = 1; + } + +return_type: + *sclass = cls; + *qualifier = qlf; + if (!tp) { + if (spec) { + tp = ctype(type, sign, size); + } else { + if (curctx != GLOBALCTX) + unexpected(); + warn("type defaults to 'int' in declaration"); + tp = inttype; + } + } + return tp; +} + +static Symbol * +newtag(void) +{ + Symbol *sym; + int ns, op, tag = yylval.token; + static unsigned tpns = NS_STRUCTS; + + ns = namespace; + namespace = NS_TAG; + next(); + namespace = ns; + + switch (yytoken) { + case IDEN: + case TYPEIDEN: + sym = yylval.sym; + if ((sym->flags & SDECLARED) == 0) + install(NS_TAG, yylval.sym); + next(); + break; + default: + sym = newsym(NS_TAG, NULL); + break; + } + if (!sym->type) { + Type *tp; + + if (tpns == NS_STRUCTS + NR_MAXSTRUCTS) + error("too many tags declared"); + tp = mktype(NULL, tag, 0, NULL); + tp->ns = tpns++; + sym->type = tp; + tp->tag = sym; + DBG("declared tag '%s' with ns = %d\n", + (sym->name) ? sym->name : "anonymous", tp->ns); + } + + if ((op = sym->type->op) != tag && op != INT) + error("'%s' defined as wrong kind of tag", sym->name); + return sym; +} + +static void fieldlist(Type *tp); + +static Type * +structdcl(void) +{ + Symbol *sym; + Type *tp; + static int nested; + int ns; + + sym = newtag(); + tp = sym->type; + + if (!accept('{')) + return tp; + + ns = namespace; + namespace = tp->ns; + + if (tp->prop & TDEFINED && sym->ctx == curctx) + error("redefinition of struct/union '%s'", sym->name); + + if (nested == NR_STRUCT_LEVEL) + error("too many levels of nested structure or union definitions"); + + ++nested; + while (yytoken != '}') { + fieldlist(tp); + } + --nested; + + deftype(tp); + namespace = ns; + expect('}'); + return tp; +} + +static Type * +enumdcl(void) +{ + Type *tp; + Symbol *sym, *tagsym; + int ns, val, toomany; + unsigned nctes; + + ns = namespace; + tagsym = newtag(); + tp = tagsym->type; + + if (!accept('{')) + goto restore_name; + if (tp->prop & TDEFINED) + errorp("redefinition of enumeration '%s'", tagsym->name); + deftype(tp); + namespace = NS_IDEN; + + /* TODO: check incorrect values in val */ + for (nctes = val = 0; yytoken != '}'; ++nctes, ++val) { + if (yytoken != IDEN) + unexpected(); + sym = yylval.sym; + next(); + if (nctes == NR_ENUM_CTES && !toomany) { + errorp("too many enum constants in a single enum"); + toomany = 1; + } + if (accept('=')) { + Node *np = constexpr(); + + if (np == NULL) + errorp("invalid enumeration value"); + else + val = np->sym->u.i; + freetree(np); + } + if ((sym = install(NS_IDEN, sym)) == NULL) { + errorp("'%s' redeclared as different kind of symbol", + yytext); + } else { + sym->u.i = val; + sym->flags |= SCONSTANT; + sym->type = inttype; + } + if (!accept(',')) + break; + } + expect('}'); + +restore_name: + namespace = ns; + return tp; +} + +static Symbol * +type(struct decl *dcl) +{ + Symbol *sym = dcl->sym; + + if (dcl->sclass) + error("class storage in type name"); + if (sym->name) + error("unexpected identifier in type name"); + sym->type = dcl->type; + + return sym; +} + +static Symbol * +field(struct decl *dcl) +{ + static char *anon = "<anonymous>"; + Symbol *sym = dcl->sym; + char *name = (sym->name) ? sym->name : anon; + Type *structp = dcl->parent, *tp = dcl->type; + TINT n = structp->n.elem; + int err = 0; + + if (accept(':')) { + Node *np; + TINT n; + + if ((np = constexpr()) == NULL) { + unexpected(); + n = 0; + } else { + n = np->sym->u.i; + freetree(np); + } + if (n == 0 && name != anon) + errorp("zero width for bit-field '%s'", name); + if (tp != booltype && tp != inttype && tp != uinttype) + errorp("bit-field '%s' has invalid type", name); + if (n < 0) + errorp("negative width in bit-field '%s'", name); + else if (n > tp->size*8) + errorp("width of '%s' exceeds its type", name); + } else if (empty(sym, tp, 0)) { + return sym; + } + + if (tp->op == FTN) { + errorp("invalid type '%s' in struct/union", name); + err = 1; + } + if (dcl->sclass) { + errorp("storage class in struct/union field '%s'", name); + err = 1; + } + if (!(tp->prop & TDEFINED)) { + error("field '%s' has incomplete type", name); + err = 1; + } + if (err) + return sym; + + if (sym->flags & SDECLARED) + error("duplicated member '%s'", name); + sym->flags |= SFIELD|SDECLARED; + sym->type = tp; + + if (n == NR_FIELDS) + error("too many fields in struct/union"); + DBG("New field '%s' in namespace %d\n", name, structp->ns); + structp->p.fields = xrealloc(structp->p.fields, ++n * sizeof(*sym)); + structp->p.fields[n-1] = sym; + structp->n.elem = n; + + return sym; +} + +static Symbol * +dodcl(int rep, Symbol *(*fun)(struct decl *), unsigned ns, Type *parent) +{ + Symbol *sym; + Type *base; + struct decl dcl; + struct declarators stack; + + dcl.ns = ns; + dcl.parent = parent; + base = specifier(&dcl.sclass, &dcl.qualifier); + + do { + dcl.type = base; + stack.nr_types = stack.nr = 0; + stack.tpars = dcl.buftpars; + stack.pars = dcl.bufpars; + stack.dcl = &dcl; + stack.ns = ns; + + declarator(&stack); + + while (pop(&stack, &dcl)) + ; + sym = (*fun)(&dcl); + if (funbody(sym, dcl.pars)) + return sym; + } while (rep && accept(',')); + + return sym; +} + +void +decl(void) +{ + Symbol *sym; + + if (accept(';')) + return; + sym = dodcl(REP, identifier, NS_IDEN, NULL); + if (sym->type->prop & TFUNDEF) + return; + expect(';'); +} + +static void +fieldlist(Type *tp) +{ + if (yytoken != ';') + dodcl(REP, field, tp->ns, tp); + expect(';'); +} + +Type * +typename(void) +{ + return dodcl(NOREP, type, NS_DUMMY, NULL)->type; +} diff --git a/src/cc1/deps.mk b/src/cc1/deps.mk @@ -0,0 +1,44 @@ +#deps +builtin.o: $(INCDIR)/scc/scc/scc.h +builtin.o: cc1.h +code.o: $(INCDIR)/scc/scc/scc.h +code.o: cc1.h +cpp.o: $(INCDIR)/scc/scc/cstd.h +cpp.o: $(INCDIR)/scc/scc/scc.h +cpp.o: cc1.h +decl.o: $(INCDIR)/scc/scc/cstd.h +decl.o: $(INCDIR)/scc/scc/scc.h +decl.o: cc1.h +error.o: $(INCDIR)/scc/scc/scc.h +error.o: cc1.h +expr.o: $(INCDIR)/scc/scc/cstd.h +expr.o: $(INCDIR)/scc/scc/scc.h +expr.o: cc1.h +fold.o: $(INCDIR)/scc/scc/scc.h +fold.o: cc1.h +init.o: $(INCDIR)/scc/scc/cstd.h +init.o: $(INCDIR)/scc/scc/scc.h +init.o: cc1.h +lex.o: $(INCDIR)/scc/scc/cstd.h +lex.o: $(INCDIR)/scc/scc/scc.h +lex.o: cc1.h +main.o: $(INCDIR)/scc/scc/arg.h +main.o: $(INCDIR)/scc/scc/scc.h +main.o: cc1.h +stmt.o: $(INCDIR)/scc/scc/cstd.h +stmt.o: $(INCDIR)/scc/scc/scc.h +stmt.o: cc1.h +symbol.o: $(INCDIR)/scc/scc/cstd.h +symbol.o: $(INCDIR)/scc/scc/scc.h +symbol.o: cc1.h +target/amd64-sysv/arch.o: $(INCDIR)/scc/scc/scc.h +target/amd64-sysv/arch.o: target/amd64-sysv/../../cc1.h +target/arm64-sysv/arch.o: $(INCDIR)/scc/scc/scc.h +target/arm64-sysv/arch.o: target/arm64-sysv/../../cc1.h +target/i386-sysv/arch.o: $(INCDIR)/scc/scc/scc.h +target/i386-sysv/arch.o: target/i386-sysv/../../cc1.h +target/z80-scc/arch.o: $(INCDIR)/scc/scc/scc.h +target/z80-scc/arch.o: target/z80-scc/../../cc1.h +types.o: $(INCDIR)/scc/scc/cstd.h +types.o: $(INCDIR)/scc/scc/scc.h +types.o: cc1.h diff --git a/src/cc1/error.c b/src/cc1/error.c @@ -0,0 +1,85 @@ +static char sccsid[] = "@(#) ./cc1/error.c"; +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> + +#include <scc/scc.h> +#include "cc1.h" + +#define MAXERRNUM 10 + +extern int failure; +static unsigned nerrors; + +static void +warn_error(int flag, char *fmt, va_list va) +{ + if (flag == 0) + return; + fprintf(stderr, "%s:%u: %s: ", + filenam, lineno, + (flag < 0) ? "error" : "warning"); + vfprintf(stderr, fmt, va); + putc('\n', stderr); + + if (flag < 0) { + if (!failure) + fclose(stdout); + failure = 1; + if (++nerrors == MAXERRNUM) { + fputs("too many errors\n", stderr); + exit(1); + } + } +} + +void +warn(char *fmt, ...) +{ + extern int warnings; + + va_list va; + va_start(va, fmt); + warn_error(warnings, fmt, va); + va_end(va); +} + +void +error(char *fmt, ...) +{ + va_list va; + + va_start(va, fmt); + warn_error(-1, fmt, va); + va_end(va); + exit(1); + discard(); +} + +void +errorp(char *fmt, ...) +{ + va_list va; + va_start(va, fmt); + warn_error(-1, fmt, va); + va_end(va); +} + +void +cpperror(char *fmt, ...) +{ + va_list va; + va_start(va, fmt); + warn_error(-1, fmt, va); + va_end(va); + + /* discard input until the end of the line */ + *input->p = '\0'; + next(); +} + +void +unexpected(void) +{ + error("unexpected '%s'", yytext); +} diff --git a/src/cc1/expr.c b/src/cc1/expr.c @@ -0,0 +1,1185 @@ +static char sccsid[] = "@(#) ./cc1/expr.c"; +#include <assert.h> +#include <stdlib.h> +#include <string.h> + +#include <scc/cstd.h> +#include <scc/scc.h> +#include "cc1.h" + +#define XCHG(lp, rp, np) (np = lp, lp = rp, rp = np) + +static Node *xexpr(void), *xassign(void); + +int +cmpnode(Node *np, TUINT val) +{ + Symbol *sym; + Type *tp; + TUINT mask, nodeval; + + if (!np || !(np->flags & NCONST) || !np->sym) + return 0; + sym = np->sym; + tp = sym->type; + + switch (tp->op) { + case PTR: + case INT: + mask = (val > 1) ? ones(np->type->size) : -1; + nodeval = (tp->prop & TSIGNED) ? sym->u.i : sym->u.u; + return (nodeval & mask) == (val & mask); + case FLOAT: + return sym->u.f == val; + } + return 0; +} + +static Node * +promote(Node *np) +{ + Type *tp; + Node *new; + struct limits *lim, *ilim; + + tp = np->type; + + switch (tp->op) { + case ENUM: + case INT: + if (tp->n.rank >= inttype->n.rank) + return np; + lim = getlimits(tp); + ilim = getlimits(inttype); + tp = (lim->max.i <= ilim->max.i) ? inttype : uinttype; + break; + case FLOAT: + /* TODO: Add support for C99 float math */ + tp = doubletype; + break; + default: + abort(); + } + if ((new = convert(np, tp, 1)) != NULL) + return new; + return np; +} + +static void +arithconv(Node **p1, Node **p2) +{ + int to = 0, s1, s2; + unsigned r1, r2; + Type *tp1, *tp2; + Node *np1, *np2; + struct limits *lp1, *lp2; + + np1 = promote(*p1); + np2 = promote(*p2); + + tp1 = np1->type; + tp2 = np2->type; + + if (tp1 == tp2) + goto set_p1_p2; + + s1 = (tp1->prop & TSIGNED) != 0; + r1 = tp1->n.rank; + lp1 = getlimits(tp1); + + s2 = (tp2->prop & TSIGNED) != 0; + r2 = tp2->n.rank; + lp2 = getlimits(tp2); + + if (s1 == s2 || tp1->op == FLOAT || tp2->op == FLOAT) { + to = r1 - r2; + } else if (!s1) { + if (r1 >= r2 || lp1->max.i >= lp2->max.i) + to = 1; + else + to = -1; + } else { + if (r2 >= r1 || lp2->max.i >= lp1->max.i) + to = -1; + else + to = 1; + } + + if (to > 0) + np2 = convert(np2, tp1, 1); + else if (to < 0) + np1 = convert(np1, tp2, 1); + +set_p1_p2: + *p1 = np1; + *p2 = np2; +} + +static int +null(Node *np) +{ + if (np->type != pvoidtype || np->op != OCAST) + return 0; + + np = np->left; + if (np->type != inttype) + return 0; + + return cmpnode(np, 0); +} + +static Node * +chkternary(Node *yes, Node *no) +{ + /* + * FIXME: + * We are ignoring type qualifiers here, + * but the standard has strong rules about this. + * take a look to 6.5.15 + */ + + if (!eqtype(yes->type, no->type, 1)) { + if ((yes->type->prop & TARITH) && (no->type->prop & TARITH)) { + arithconv(&yes, &no); + } else if (yes->type->op != PTR && no->type->op != PTR) { + goto wrong_type; + } else { + /* convert integer 0 to NULL */ + if ((yes->type->prop & TINTEGER) && cmpnode(yes, 0)) + yes = convert(yes, pvoidtype, 0); + if ((no->type->prop & TINTEGER) && cmpnode(no, 0)) + no = convert(no, pvoidtype, 0); + /* + * At this point the type of both should be + * a pointer to something, or we have don't + * compatible types + */ + if (yes->type->op != PTR || no->type->op != PTR) + goto wrong_type; + /* + * If we have a null pointer constant then + * convert to the another type + */ + if (null(yes)) + yes = convert(yes, no->type, 0); + if (null(no)) + no = convert(no, yes->type, 0); + + if (!eqtype(yes->type, no->type, 1)) + goto wrong_type; + } + } + return node(OCOLON, yes->type, yes, no); + +wrong_type: + errorp("type mismatch in conditional expression"); + freetree(yes); + freetree(no); + return constnode(zero); +} + +static void +chklvalue(Node *np) +{ + if (!(np->flags & NLVAL)) + errorp("lvalue required in operation"); + if (np->type == voidtype) + errorp("invalid use of void expression"); +} + +Node * +decay(Node *np) +{ + Node *new; + Type *tp = np->type; + + switch (tp->op) { + case ARY: + tp = tp->type; + if (np->op == OPTR) { + new = np->left; + free(np); + new->type = mktype(tp, PTR, 0, NULL); + return new; + } + case FTN: + new = node(OADDR, mktype(tp, PTR, 0, NULL), np, NULL); + if (np->sym && np->sym->flags & (SGLOBAL|SLOCAL|SPRIVATE)) + new->flags |= NCONST; + return new; + default: + return np; + } +} + +static Node * +integerop(int op, Node *lp, Node *rp) +{ + if (!(lp->type->prop & TINTEGER) || !(rp->type->prop & TINTEGER)) + error("operator requires integer operands"); + arithconv(&lp, &rp); + return node(op, lp->type, lp, rp); +} + +static Node * +integeruop(int op, Node *np) +{ + if (!(np->type->prop & TINTEGER)) + error("unary operator requires integer operand"); + np = promote(np); + return node(op, np->type, np, NULL); +} + +static Node * +numericaluop(int op, Node *np) +{ + if (!(np->type->prop & TARITH)) + error("unary operator requires numerical operand"); + np = promote(np); + return node(op, np->type, np, NULL); +} + +Node * +convert(Node *np, Type *newtp, int iscast) +{ + Type *oldtp = np->type; + + if (eqtype(newtp, oldtp, 0)) + return np; + + switch (oldtp->op) { + case ENUM: + case INT: + case FLOAT: + switch (newtp->op) { + case PTR: + if (oldtp->op == FLOAT || !cmpnode(np, 0) && !iscast) + return NULL; + case INT: + case FLOAT: + case ENUM: + break; + default: + return NULL; + } + break; + case PTR: + switch (newtp->op) { + case ENUM: + case INT: + case VOID: + if (!iscast) + return NULL; + break; + case PTR: + if (eqtype(newtp, oldtp, 1) || + iscast || + newtp == pvoidtype || oldtp == pvoidtype) { + np->type = newtp; + return np; + } + default: + return NULL; + } + break; + default: + return NULL; + } + return node(OCAST, newtp, np, NULL); +} + +static Node * +parithmetic(int op, Node *lp, Node *rp) +{ + Type *tp; + Node *size, *np; + + if (lp->type->op != PTR) + XCHG(lp, rp, np); + + tp = rp->type; + if (tp->op == PTR && !(tp->type->prop & TDEFINED)) + goto incomplete; + tp = lp->type; + if (!(tp->type->prop & TDEFINED)) + goto incomplete; + size = sizeofnode(tp->type); + + if (op == OSUB && BTYPE(rp) == PTR) { + if ((rp = convert(rp, lp->type, 0)) == NULL) + goto incorrect; + lp = node(OSUB, pdifftype, lp, rp); + return node(ODIV, inttype, lp, size); + } + if (!(rp->type->prop & TINTEGER)) + goto incorrect; + + rp = convert(promote(rp), sizettype, 0); + rp = node(OMUL, sizettype, rp, size); + rp = convert(rp, tp, 1); + + return node(op, tp, lp, rp); + +incomplete: + errorp("invalid use of undefined type"); + return lp; +incorrect: + errorp("incorrect arithmetic operands"); + return lp; + +} + +static Node * +arithmetic(int op, Node *lp, Node *rp) +{ + Type *ltp = lp->type, *rtp = rp->type; + + if ((ltp->prop & TARITH) && (rtp->prop & TARITH)) { + arithconv(&lp, &rp); + return node(op, lp->type, lp, rp); + } else if ((ltp->op == PTR || rtp->op == PTR)) { + switch (op) { + case OADD: + case OSUB: + case OA_ADD: + case OA_SUB: + case OINC: + case ODEC: + return parithmetic(op, lp, rp); + } + } + errorp("incorrect arithmetic operands"); +} + +static Node * +pcompare(int op, Node *lp, Node *rp) +{ + Node *np; + + if (lp->type->prop & TINTEGER) + XCHG(lp, rp, np); + else if (eqtype(lp->type, pvoidtype, 1)) + XCHG(lp, rp, np); + + if ((np = convert(rp, lp->type, 0)) != NULL) + rp = np; + else + errorp("incompatible types in comparison"); + return convert(node(op, pvoidtype, lp, rp), inttype, 1); +} + +static Node * +compare(int op, Node *lp, Node *rp) +{ + Type *ltp, *rtp; + + ltp = lp->type; + rtp = rp->type; + + if (ltp->op == PTR || rtp->op == PTR) { + return pcompare(op, rp, lp); + } else if ((ltp->prop & TARITH) && (rtp->prop & TARITH)) { + arithconv(&lp, &rp); + return convert(node(op, lp->type, lp, rp), inttype, 1);; + } else { + errorp("incompatible types in comparison"); + freetree(lp); + freetree(rp); + return constnode(zero); + } +} + +int +negop(int op) +{ + switch (op) { + case OEQ: return ONE; + case ONE: return OEQ; + case OLT: return OGE; + case OGE: return OLT; + case OLE: return OGT; + case OGT: return OLE; + default: abort(); + } + return op; +} + +static Node * +exp2cond(Node *np, int neg) +{ + if (np->type->prop & TAGGREG) { + errorp("used struct/union type value where scalar is required"); + return constnode(zero); + } + switch (np->op) { + case ONEG: + case OOR: + case OAND: + return (neg) ? node(ONEG, inttype, np, NULL) : np; + case OEQ: + case ONE: + case OLT: + case OGE: + case OLE: + case OGT: + if (neg) + np->op = negop(np->op); + return np; + default: + return compare((neg) ? OEQ : ONE, np, constnode(zero)); + } +} + +static Node * +logic(int op, Node *lp, Node *rp) +{ + lp = exp2cond(lp, 0); + rp = exp2cond(rp, 0); + return node(op, inttype, lp, rp); +} + +static Node * +field(Node *np) +{ + Symbol *sym; + + namespace = np->type->ns; + next(); + namespace = NS_IDEN; + + sym = yylval.sym; + if (yytoken != IDEN) + unexpected(); + next(); + + if (!(np->type->prop & TAGGREG)) { + errorp("request for member '%s' in something not a structure or union", + yylval.sym->name); + goto free_np; + } + if ((sym->flags & SDECLARED) == 0) { + errorp("incorrect field in struct/union"); + goto free_np; + } + np = node(OFIELD, sym->type, np, varnode(sym)); + np->flags |= NLVAL; + return np; + +free_np: + freetree(np); + return constnode(zero); +} + +static Node * +content(int op, Node *np) +{ + if (BTYPE(np) != PTR) { + errorp("invalid argument of memory indirection"); + } else { + if (np->op == OADDR) { + Node *new = np->left; + new->type = np->type->type; + free(np); + np = new; + } else { + np = node(op, np->type->type, np, NULL); + } + np->flags |= NLVAL; + } + return np; +} + +static Node * +array(Node *lp, Node *rp) +{ + Type *tp; + Node *np; + + if (!(lp->type->prop & TINTEGER) && !(rp->type->prop & TINTEGER)) + error("array subscript is not an integer"); + np = arithmetic(OADD, lp, rp); + tp = np->type; + if (tp->op != PTR) + errorp("subscripted value is neither array nor pointer"); + return content(OPTR, np); +} + +static Node * +assignop(int op, Node *lp, Node *rp) +{ + if ((rp = convert(rp, lp->type, 0)) == NULL) { + errorp("incompatible types when assigning"); + return lp; + } + + return node(op, lp->type, lp, rp); +} + +static Node * +incdec(Node *np, int op) +{ + Type *tp = np->type; + Node *inc; + + chklvalue(np); + np->flags |= NEFFECT; + + if (!(tp->prop & TDEFINED)) { + errorp("invalid use of undefined type"); + return np; + } else if (tp->op == PTR && !(tp->type->prop & TDEFINED)) { + errorp("%s of pointer to an incomplete type", + (op == OINC || op == OA_ADD) ? "increment" : "decrement"); + return np; + } else if (tp->op == PTR || (tp->prop & TARITH)) { + inc = constnode(one); + } else { + errorp("wrong type argument to increment or decrement"); + return np; + } + return arithmetic(op, np, inc); +} + +static Node * +address(int op, Node *np) +{ + Node *new; + + /* + * ansi c accepts & applied to a function name, and it generates + * a function pointer + */ + if (np->op == OSYM) { + if (np->type->op == FTN) + return decay(np); + if (np->type->op == ARY) + goto dont_check_lvalue; + } + chklvalue(np); + +dont_check_lvalue: + if (np->sym && (np->sym->flags & SREGISTER)) + errorp("address of register variable '%s' requested", yytext); + new = node(op, mktype(np->type, PTR, 0, NULL), np, NULL); + if (np->sym && np->sym->flags & (SGLOBAL|SLOCAL|SPRIVATE)) + new->flags |= NCONST; + return new; +} + +static Node * +negation(int op, Node *np) +{ + if (!(np->type->prop & TARITH) && np->type->op != PTR) { + errorp("invalid argument of unary '!'"); + return constnode(zero); + } + return exp2cond(np, 1); +} + +static Symbol * +notdefined(Symbol *sym) +{ + int isdef; + + if (namespace == NS_CPP && !strcmp(sym->name, "defined")) { + disexpand = 1; + next(); + expect('('); + sym = yylval.sym; + expect(IDEN); + expect(')'); + + isdef = (sym->flags & SDECLARED) != 0; + sym = newsym(NS_IDEN, NULL); + sym->type = inttype; + sym->flags |= SCONSTANT; + sym->u.i = isdef; + disexpand = 0; + return sym; + } + errorp("'%s' undeclared", yytext); + sym->type = inttype; + return install(sym->ns, yylval.sym); +} + +static Symbol * +adjstrings(Symbol *sym) +{ + char *s, *t; + size_t len, n; + Type *tp; + + tp = sym->type; + s = sym->u.s; + for (len = strlen(s);; len += n) { + next(); + if (yytoken != STRING) + break; + t = yylval.sym->u.s; + n = strlen(t); + s = xrealloc(s, len + n + 1); + memcpy(s+len, t, n); + s[len + n] = '\0'; + killsym(yylval.sym); + } + ++len; + if (tp->n.elem != len) { + sym->type = mktype(chartype, ARY, len, NULL); + sym->u.s = s; + } + return sym; +} + +/************************************************************* + * grammar functions * + *************************************************************/ +static Node * +primary(void) +{ + Node *np; + Symbol *sym; + Node *(*fun)(Symbol *); + + sym = yylval.sym; + switch (yytoken) { + case STRING: + np = constnode(adjstrings(sym)); + sym->flags |= SHASINIT; + emit(ODECL, sym); + emit(OINIT, np); + return varnode(sym); + case BUILTIN: + fun = sym->u.fun; + next(); + expect('('); + np = (*fun)(sym); + expect(')'); + + /* do not call to next */ + return np; + case CONSTANT: + np = constnode(sym); + break; + case IDEN: + assert((sym->flags & SCONSTANT) == 0); + if ((sym->flags & SDECLARED) == 0) { + if (namespace == NS_CPP) { + np = constnode(zero); + break; + } + sym = notdefined(sym); + } + sym->flags |= SUSED; + np = varnode(sym); + break; + default: + unexpected(); + } + next(); + + return np; +} + +static Node * +arguments(Node *np) +{ + int toomany, n, op; + Node *par = NULL, *arg; + Type *argtype, **targs, *tp = np->type, *rettype; + + if (tp->op == PTR && tp->type->op == FTN) { + np = content(OPTR, np); + tp = np->type; + } + if (tp->op != FTN) { + targs = (Type *[]) {ellipsistype}; + n = 1; + rettype = inttype; + errorp("function or function pointer expected"); + } else { + targs = tp->p.pars; + n = tp->n.elem; + rettype = tp->type; + } + + expect('('); + if (yytoken == ')') + goto no_pars; + toomany = 0; + + do { + arg = xassign(); + argtype = *targs; + if (argtype == ellipsistype) { + n = 0; + switch (arg->type->op) { + case INT: + arg = promote(arg); + break; + case FLOAT: + if (arg->type == floattype) + arg = convert(arg, doubletype, 1); + break; + } + par = node(OPAR, arg->type, par, arg); + continue; + } + if (--n < 0) { + if (!toomany) + errorp("too many arguments in function call"); + toomany = 1; + continue; + } + ++targs; + if ((arg = convert(arg, argtype, 0)) != NULL) { + par = node(OPAR, arg->type, par, arg); + continue; + } + errorp("incompatible type for argument %d in function call", + tp->n.elem - n + 1); + } while (accept(',')); + +no_pars: + expect(')'); + if (n > 0 && *targs != ellipsistype) + errorp("too few arguments in function call"); + + op = (tp->prop&TELLIPSIS) ? OCALLE : OCALL; + return node(op, rettype, np, par); +} + +static Node *unary(int); + +static Type * +typeof(Node *np) +{ + Type *tp; + + if (np == NULL) + unexpected(); + tp = np->type; + freetree(np); + return tp; +} + +static Type * +sizeexp(void) +{ + Type *tp; + + expect('('); + switch (yytoken) { + case TYPE: + case TYPEIDEN: + tp = typename(); + break; + default: + tp = typeof(unary(0)); + break; + } + expect(')'); + return tp; +} + +static Node * +postfix(Node *lp) +{ + Node *rp; + + for (;;) { + switch (yytoken) { + case '[': + case DEC: + case INC: + case INDIR: + case '.': + case '(': + lp = decay(lp); + switch (yytoken) { + case '[': + next(); + rp = xexpr(); + expect(']'); + lp = array(lp, rp); + break; + case DEC: + case INC: + lp = incdec(lp, (yytoken == INC) ? OINC : ODEC); + next(); + break; + case INDIR: + lp = content(OPTR, lp); + case '.': + lp = field(lp); + break; + case '(': + lp = arguments(lp); + lp->flags |= NEFFECT; + break; + } + break; + default: + return lp; + } + } +} + +static Node * +defined(void) +{ + Symbol *sym; + int paren; + + disexpand = 1; + next(); + paren = accept('('); + if (yytoken != IDEN && yytoken != TYPEIDEN) + cpperror("operator 'defined' requires an identifier"); + if (yytoken == TYPEIDEN || !(yylval.sym->flags & SDECLARED)) + sym = zero; + else + sym = one; + disexpand = 0; + next(); + if (paren) + expect(')'); + return constnode(sym); +} + +static Node *cast(int); + +static Node * +unary(int needdecay) +{ + Node *(*fun)(int, Node *), *np; + int op; + Type *tp; + + switch (yytoken) { + case '!': op = 0; fun = negation; break; + case '+': op = OADD; fun = numericaluop; break; + case '-': op = OSNEG; fun = numericaluop; break; + case '~': op = OCPL; fun = integeruop; break; + case '&': op = OADDR; fun = address; break; + case '*': op = OPTR; fun = content; break; + case SIZEOF: + next(); + tp = (yytoken == '(') ? sizeexp() : typeof(unary(0)); + if (!(tp->prop & TDEFINED)) + errorp("sizeof applied to an incomplete type"); + return sizeofnode(tp); + case INC: + case DEC: + op = (yytoken == INC) ? OA_ADD : OA_SUB; + next(); + np = incdec(unary(1), op); + goto chk_decay; + case IDEN: + case TYPEIDEN: + if (lexmode == CPPMODE && !strcmp(yylval.sym->name, "defined")) + return defined(); + default: + np = postfix(primary()); + goto chk_decay; + } + + next(); + np = (*fun)(op, cast(op != OADDR)); + +chk_decay: + if (needdecay) + np = decay(np); + return np; +} + +static Node * +cast(int needdecay) +{ + Node *lp, *rp; + Type *tp; + static int nested; + + if (!accept('(')) + return unary(needdecay); + + switch (yytoken) { + case TQUALIFIER: + case TYPE: + case TYPEIDEN: + tp = typename(); + expect(')'); + + if (yytoken == '{') + return initlist(tp); + + switch (tp->op) { + case ARY: + error("cast specifies an array type"); + default: + lp = cast(needdecay); + if ((rp = convert(lp, tp, 1)) == NULL) + error("bad type conversion requested"); + rp->flags &= ~NLVAL; + rp->flags |= lp->flags & NLVAL; + } + break; + default: + if (nested == NR_SUBEXPR) + error("too many expressions nested by parentheses"); + ++nested; + rp = xexpr(); + --nested; + expect(')'); + rp = postfix(rp); + break; + } + + return rp; +} + +static Node * +mul(void) +{ + Node *np, *(*fun)(int, Node *, Node *); + int op; + + np = cast(1); + for (;;) { + switch (yytoken) { + case '*': op = OMUL; fun = arithmetic; break; + case '/': op = ODIV; fun = arithmetic; break; + case '%': op = OMOD; fun = integerop; break; + default: return np; + } + next(); + np = (*fun)(op, np, cast(1)); + } +} + +static Node * +add(void) +{ + int op; + Node *np; + + np = mul(); + for (;;) { + switch (yytoken) { + case '+': op = OADD; break; + case '-': op = OSUB; break; + default: return np; + } + next(); + np = arithmetic(op, np, mul()); + } +} + +static Node * +shift(void) +{ + int op; + Node *np; + + np = add(); + for (;;) { + switch (yytoken) { + case SHL: op = OSHL; break; + case SHR: op = OSHR; break; + default: return np; + } + next(); + np = integerop(op, np, add()); + } +} + +static Node * +relational(void) +{ + int op; + Node *np; + + np = shift(); + for (;;) { + switch (yytoken) { + case '<': op = OLT; break; + case '>': op = OGT; break; + case GE: op = OGE; break; + case LE: op = OLE; break; + default: return np; + } + next(); + np = compare(op, np, shift()); + } +} + +static Node * +eq(void) +{ + int op; + Node *np; + + np = relational(); + for (;;) { + switch (yytoken) { + case EQ: op = OEQ; break; + case NE: op = ONE; break; + default: return np; + } + next(); + np = compare(op, np, relational()); + } +} + +static Node * +bit_and(void) +{ + Node *np; + + np = eq(); + while (accept('&')) + np = integerop(OBAND, np, eq()); + return np; +} + +static Node * +bit_xor(void) +{ + Node *np; + + np = bit_and(); + while (accept('^')) + np = integerop(OBXOR, np, bit_and()); + return np; +} + +static Node * +bit_or(void) +{ + Node *np; + + np = bit_xor(); + while (accept('|')) + np = integerop(OBOR, np, bit_xor()); + return np; +} + +static Node * +and(void) +{ + Node *np; + + np = bit_or(); + while (accept(AND)) + np = logic(OAND, np, bit_or()); + return np; +} + +static Node * +or(void) +{ + Node *np; + + np = and(); + while (accept(OR)) + np = logic(OOR, np, and()); + return np; +} + +static Node * +ternary(void) +{ + Node *cond; + + cond = or(); + while (accept('?')) { + Node *ifyes, *ifno, *np; + + cond = exp2cond(cond, 0); + ifyes = xexpr(); + expect(':'); + ifno = ternary(); + np = chkternary(ifyes, ifno); + cond = node(OASK, np->type, cond, np); + } + return cond; +} + +static Node * +xassign(void) +{ + Node *np, *(*fun)(int , Node *, Node *); + int op; + + np = ternary(); + for (;;) { + switch (yytoken) { + case '=': op = OASSIGN; fun = assignop; break; + case MUL_EQ: op = OA_MUL; fun = arithmetic; break; + case DIV_EQ: op = OA_DIV; fun = arithmetic; break; + case MOD_EQ: op = OA_MOD; fun = integerop; break; + case ADD_EQ: op = OA_ADD; fun = arithmetic; break; + case SUB_EQ: op = OA_SUB; fun = arithmetic; break; + case SHL_EQ: op = OA_SHL; fun = integerop; break; + case SHR_EQ: op = OA_SHR; fun = integerop; break; + case AND_EQ: op = OA_AND; fun = integerop; break; + case XOR_EQ: op = OA_XOR; fun = integerop; break; + case OR_EQ: op = OA_OR; fun = integerop; break; + default: return np; + } + chklvalue(np); + np->flags |= NEFFECT; + next(); + np = (fun)(op, np, assign()); + } +} + +static Node * +xexpr(void) +{ + Node *lp, *rp; + + lp = xassign(); + while (accept(',')) { + rp = xassign(); + lp = node(OCOMMA, rp->type, lp, rp); + } + return lp; +} + +Node * +assign(void) +{ + return simplify(xassign()); +} + +Node * +constexpr(void) +{ + Node *np; + + np = ternary(); + if (np && np->type->op == INT) { + np = simplify(convert(np, inttype, 0)); + if (np->flags & NCONST) + return np; + } + freetree(np); + return NULL; +} + +Node * +expr(void) +{ + return simplify(xexpr()); +} + +Node * +condexpr(int neg) +{ + Node *np; + + np = exp2cond(xexpr(), neg); + if (np->flags & NCONST) + warn("conditional expression is constant"); + return simplify(np); +} diff --git a/src/cc1/fold.c b/src/cc1/fold.c @@ -0,0 +1,685 @@ +static char sccsid[] = "@(#) ./cc1/fold.c"; +#include <assert.h> +#include <stdlib.h> + +#include <scc/scc.h> +#include "cc1.h" + + +TUINT +ones(int nbytes) +{ + return (nbytes == 8) ? -1 : ~(-1ull << nbytes * 8); +} + +static int +addi(TINT l, TINT r, Type *tp) +{ + struct limits *lim = getlimits(tp); + TINT max = lim->max.i, min = -lim->min.i; + + if (l < 0 && r < 0 && l >= min - r || + l == 0 || + r == 0 || + l < 0 && r > 0 || + l > 0 && r < 0 || + l > 0 && r > 0 && l <= max - r) { + return 1; + } + warn("overflow in constant expression"); + return 0; +} + +static int +addf(TFLOAT l, TFLOAT r, Type *tp) +{ + struct limits *lim = getlimits(tp); + TFLOAT max = lim->max.f, min = lim->min.f; + + if (l < 0 && r < 0 && l >= min - r || + l == 0 || + r == 0 || + l < 0 && r > 0 || + l > 0 && r < 0 || + l > 0 && r > 0 && l <= max - r) { + return 1; + } + warn("overflow in constant expression"); + return 0; +} + +static int +subi(TINT l, TINT r, Type *tp) +{ + return addi(l, -r, tp); +} + +static int +subf(TFLOAT l, TFLOAT r, Type *tp) +{ + return addf(l, -r, tp); +} + +static int +muli(TINT l, TINT r, Type *tp) +{ + struct limits *lim = getlimits(tp); + TINT max = lim->max.i, min = -lim->min.i; + + if (l > -1 && l <= 1 || + r > -1 && r <= 1 || + l < 0 && r < 0 && -l <= max/-r || + l < 0 && r > 0 && l >= min/r || + l > 0 && r < 0 && r >= min/l || + l > 0 && r > 0 && l <= max/r) { + return 1; + } + warn("overflow in constant expression"); + return 0; +} + +static int +mulf(TFLOAT l, TFLOAT r, Type *tp) +{ + struct limits *lim = getlimits(tp); + TFLOAT max = lim->max.f, min = lim->min.f; + + if (l > -1 && l <= 1 || + r > -1 && r <= 1 || + l < 0 && r < 0 && -l <= max/-r || + l < 0 && r > 0 && l >= min/r || + l > 0 && r < 0 && r >= min/l || + l > 0 && r > 0 && l <= max/r) { + return 1; + } + warn("overflow in constant expression"); + return 0; +} + +static int +divi(TINT l, TINT r, Type *tp) +{ + struct limits *lim = getlimits(tp); + + if (r == 0 || l == -lim->min.i && r == -1) { + warn("overflow in constant expression"); + return 0; + } + return 1; +} + +static int +divf(TFLOAT l, TFLOAT r, Type *tp) +{ + struct limits *lim = getlimits(tp); + + if (l < 0) l = -l; + if (r < 0) r = -r; + + if (r == 0.0 || r < 1.0 && l > lim->max.f * r) { + warn("overflow in constant expression"); + return 0; + } + return 1; +} + +static int +lshi(TINT l, TINT r, Type *tp) +{ + if (r < 0 || r >= tp->size * 8) { + warn("shifting %d bits is undefined", r); + return 0; + } + return muli(l, 1 << r, tp); +} + +static int +rshi(TINT l, TINT r, Type *tp) +{ + if (r < 0 || r >= tp->size * 8) { + warn("shifting %d bits is undefined", r); + return 0; + } + return 1; +} + +static int +foldint(int op, Symbol *res, TINT l, TINT r) +{ + TINT i; + Type *tp = res->type; + int (*validate)(TINT, TINT, Type *tp); + + switch (op) { + case OADD: validate = addi; break; + case OSUB: validate = subi; break; + case OMUL: validate = muli; break; + case ODIV: validate = divi; break; + case OSHL: validate = lshi; break; + case OSHR: validate = rshi; break; + case OMOD: validate = divi; break; + default: validate = NULL; break; + } + + if (validate && !(*validate)(l, r, tp)) + return 0; + + switch (op) { + case OADD: i = l + r; break; + case OSUB: i = l - r; break; + case OMUL: i = l * r; break; + case ODIV: i = l / r; break; + case OMOD: i = l % r; break; + case OSHL: i = l << r; break; + case OSHR: i = l >> r; break; + case OBAND: i = l & r; break; + case OBXOR: i = l ^ r; break; + case OBOR: i = l | r; break; + case OAND: i = l && r; break; + case OOR: i = l || r; break; + case OLT: i = l < r; break; + case OGT: i = l > r; break; + case OGE: i = l >= r; break; + case OLE: i = l <= r; break; + case OEQ: i = l == r; break; + case ONE: i = l != r; break; + case ONEG: i = !l; break; + case OSNEG: i = -l; break; + case OCPL: i = ~l; break; + default: return 0; + } + res->u.i = i; + + DBG("FOLD i l=%lld %d r=%lld = %lld", l, op, r, i); + return 1; +} + +static int +folduint(int op, Symbol *res, TUINT l, TUINT r) +{ + TINT i; + TUINT u; + + switch (op) { + case OADD: u = l + r; break; + case OSUB: u = l - r; break; + case OMUL: u = l * r; break; + case ODIV: u = l / r; break; + case OMOD: u = l % r; break; + case OSHL: u = l << r; break; + case OSHR: u = l >> r; break; + case OBAND: u = l & r; break; + case OBXOR: u = l ^ r; break; + case OBOR: u = l | r; break; + case ONEG: u = !l; break; + case OSNEG: u = -l; break; + case OCPL: u = ~l; break; + case OAND: i = l && r; goto sign; + case OOR: i = l || r; goto sign; + case OLT: i = l < r; goto sign; + case OGT: i = l > r; goto sign; + case OGE: i = l >= r; goto sign; + case OLE: i = l <= r; goto sign; + case OEQ: i = l == r; goto sign; + case ONE: i = l != r; goto sign; + default: return 0; + } + res->u.u = u & ones(res->type->size); + + DBG("FOLD ui l=%llu %d r=%llu = %llu", l, op, r, u); + return 1; + +sign: + res->u.i = i; + + DBG("FOLD sui %llu %d %llu = %llu", l, op, r, i); + return 1; +} + +static int +foldfloat(int op, Symbol *res, TFLOAT l, TFLOAT r) +{ + TFLOAT f; + TINT i; + int (*validate)(TFLOAT, TFLOAT, Type *tp); + + switch (op) { + case OADD: validate = addf; break; + case OSUB: validate = subf; break; + case OMUL: validate = mulf; break; + case ODIV: validate = divf; break; + default: validate = NULL; break; + } + + if (validate && !(*validate)(l, r, res->type)) + return 0; + + switch (op) { + case OADD: f = l + r; break; + case OSUB: f = l - r; break; + case OMUL: f = l * r; break; + case ODIV: f = l / r; break; + case OLT: i = l < r; goto comparison; + case OGT: i = l > r; goto comparison; + case OGE: i = l >= r; goto comparison; + case OLE: i = l <= r; goto comparison; + case OEQ: i = l == r; goto comparison; + case ONE: i = l != r; goto comparison; + default: return 0; + } + res->u.f = f; + + DBG("FOLD f l=%lf %d r=%lf = %lf", l, op, r, f); + return 1; + +comparison: + res->u.i = i; + + DBG("FOLD if l=%lf %d r=%lf = %lld", l, op, r, i); + return 1; +} + +static Node * +foldconst(int type, int op, Type *tp, Symbol *ls, Symbol *rs) +{ + Symbol *sym, aux; + TINT i; + TUINT u; + TFLOAT f; + + aux.type = tp; + switch (type) { + case INT: + i = (rs) ? rs->u.i : 0; + if (!foldint(op, &aux, ls->u.i, i)) + return NULL; + break; + case UNSIGNED: + u = (rs) ? rs->u.u : 0u; + if (!folduint(op, &aux, ls->u.u, u)) + return NULL; + break; + case FLOAT: + f = (rs) ? rs->u.f : 0.0; + if (!foldfloat(op, &aux, ls->u.f, f)) + return NULL; + break; + } + sym = newsym(NS_IDEN, NULL); + sym->flags |= SCONSTANT; + sym->type = tp; + sym->u = aux.u; + return constnode(sym); +} + +static Node * +foldcast(Node *np, Node *l) +{ + TUINT negmask, mask, u; + Type *newtp = np->type, *oldtp = l->type; + Symbol aux, *sym, *osym = l->sym; + + if (!(l->flags & NCONST)) + return np; + + switch (newtp->op) { + case PTR: + case INT: + case ENUM: + switch (oldtp->op) { + case PTR: + case INT: + case ENUM: + u = (oldtp->prop & TSIGNED) ? osym->u.i : osym->u.u; + break; + case FLOAT: + oldtp = newtp; + u = osym->u.f; + break; + default: + return np; + } + mask = ones(newtp->size); + if (newtp->prop & TSIGNED) { + negmask = ~mask; + if (u & (negmask >> 1) & mask) + u |= negmask; + aux.u.i = u; + } else { + aux.u.u = u & mask; + } + break; + case FLOAT: + /* FIXME: The cast can be from another float type */ + aux.u.f = (oldtp->prop & TSIGNED) ? osym->u.i : osym->u.u; + break; + default: + return np; + } + DBG("FOLD cast %c->%c", oldtp->letter, newtp->letter); + freetree(np); + sym = newsym(NS_IDEN, NULL); + sym->flags |= SCONSTANT; + sym->type = newtp; + sym->u = aux.u; + return constnode(sym); +} + +static Node * +foldunary(Node *np, Node *l) +{ + int op = l->op; + Node *aux; + + switch (np->op) { + case ONEG: + if (l->op == ONEG) + break; + return NULL; + case OADD: + DBG("FOLD unary delete %d", np->op); + np->left = NULL; + freetree(np); + return l; + case OCAST: + if (op != OCAST) + return foldcast(np, l); + /* TODO: This is wrong: (float)(int) 7.2 */ + DBG("FOLD unary collapse %d", np->op); + np->left = l->left; + l->left = NULL; + freetree(l); + return np; + case OSNEG: + case OCPL: + if (op != np->op) + return NULL; + break; + case OPTR: + if (op != OADDR || np->type != l->left->type) + return NULL; + break; + case OADDR: + if (op != OPTR) + return NULL; + break; + default: + return NULL; + } + DBG("FOLD unary cancel %d", np->op); + aux = l->left; + l->left = NULL; + freetree(np); + return aux; +} + +static Node * +fold(Node *np) +{ + Symbol *rs, *ls; + Type *optype; + int type; + int op = np->op; + Node *p, *lp = np->left, *rp = np->right; + Type *tp = np->type; + + assert(lp && rp); + if ((op == ODIV || op == OMOD) && cmpnode(rp, 0)) { + warn("division by 0"); + return NULL; + } + /* + * Return if any of the children is no constant, + * or it is a constant generated when + * the address of a static variable is taken + * (when we don't know the physical address so + * we cannot fold it) + */ + if (!rp) { + rs = NULL; + } else { + if (!(rp->flags & NCONST) || !rp->sym) + return NULL; + rs = rp->sym; + } + + if (!(lp->flags & NCONST) || !lp->sym) + return NULL; + optype = lp->type; + ls = lp->sym; + + switch (type = optype->op) { + case ENUM: + case INT: + if (!(optype->prop & TSIGNED)) + type = UNSIGNED; + case PTR: + case FLOAT: + if ((p = foldconst(type, op, tp, ls, rs)) == NULL) + return NULL; + freetree(np); + return p; + default: + return NULL; + } +} + +static void +commutative(Node *np, Node *l, Node *r) +{ + int op = np->op; + + if (r == NULL || r->flags&NCONST || !(l->flags&NCONST)) + return; + + switch (op) { + case OLT: + case OGT: + case OGE: + case OLE: + DBG("FOLD neg commutative %d", np->op); + np->op = negop(op); + case OEQ: + case ONE: + case OADD: + case OMUL: + case OBAND: + case OBXOR: + case OBOR: + DBG("FOLD commutative %d", np->op); + np->left = r; + np->right = l; + break; + } +} + +static Node * +identity(Node *np) +{ + int iszeror, isoner; + int iszerol, isonel; + Node *lp = np->left, *rp = np->right; + + if (!rp) + return NULL; + + iszeror = cmpnode(rp, 0); + isoner = cmpnode(rp, 1), + iszerol = cmpnode(lp, 0); + isonel = cmpnode(lp, 1); + + switch (np->op) { + case OOR: + /* + * 1 || i => 1 (free right) + * i || 0 => i (free right) + * 0 || i => i (free left) + * i || 1 => i,1 (comma) + */ + if (isonel | iszeror) + goto free_right; + if (iszerol) + goto free_left; + if (isoner) + goto change_to_comma; + return NULL; + case OAND: + /* + * 0 && i => 0 (free right) + * i && 1 => i (free right) + * 1 && i => i (free left) + * i && 0 => i,0 (comma) + */ + if (iszerol | isoner) + goto free_right; + if (isonel) + goto free_left; + if (iszeror) + goto change_to_comma; + return NULL; + case OSHL: + case OSHR: + /* + * i >> 0 => i (free right) + * i << 0 => i (free right) + * 0 >> i => 0 (free right) + * 0 << i => 0 (free right) + */ + if (iszeror | iszerol) + goto free_right; + return NULL; + case OBXOR: + case OADD: + case OBOR: + case OSUB: + /* + * i + 0 => i + * i - 0 => i + * i | 0 => i + * i ^ 0 => i + */ + if (iszeror) + goto free_right; + return NULL; + case OMUL: + /* + * i * 0 => i,0 + * i * 1 => i + */ + if (iszeror) + goto change_to_comma; + if (isoner) + goto free_right; + return NULL; + case ODIV: + /* i / 1 => i */ + if (isoner) + goto free_right; + return NULL; + case OBAND: + /* i & ~0 => i */ + if (cmpnode(rp, -1)) + goto free_right; + return NULL; + case OMOD: + /* i % 1 => i,1 */ + /* TODO: i % 2^n => i & n-1 */ + if (isoner) + goto change_to_comma; + default: + return NULL; + } + +free_right: + DBG("FOLD identity %d", np->op); + np->left = NULL; + freetree(np); + return lp; + +free_left: + DBG("FOLD identity %d", np->op); + np->right = NULL; + freetree(np); + return rp; + +change_to_comma: + DBG("FOLD identity %d", np->op); + np->op = OCOMMA; + return np; +} + +static Node * +foldternary(Node *np, Node *cond, Node *body) +{ + if (!(cond->flags & NCONST)) + return np; + if (cmpnode(cond, 0)) { + np = body->right; + freetree(body->left); + } else { + np = body->left; + freetree(body->right); + } + + DBG("FOLD ternary"); + body->left = NULL; + body->right = NULL; + freetree(cond); + free(body); + return np; +} + +/* TODO: fold OCOMMA */ + +Node * +simplify(Node *np) +{ + Node *p, *l, *r; + + if (!np) + return NULL; + if (debug) + prtree(np); + + l = np->left = simplify(np->left); + r = np->right = simplify(np->right); + + switch (np->op) { + case OASK: + return foldternary(np, l, r); + case OCALL: + case OPAR: + case OSYM: + case OASSIGN: + case OA_MUL: + case OA_DIV: + case OA_MOD: + case OA_ADD: + case OA_SUB: + case OA_SHL: + case OA_SHR: + case OA_AND: + case OA_XOR: + case OA_OR: + return np; + case OSNEG: + case OCPL: + case OADDR: + case OPTR: + case INC: + case DEC: + case OCAST: + case ONEG: + assert(!r); + if ((p = foldunary(np, l)) != NULL) + return p; + return np; + default: + commutative(np, l, r); + if ((p = fold(np)) != NULL) + return p; + if ((p = identity(np)) != NULL) + return p; + return np; + } +} diff --git a/src/cc1/init.c b/src/cc1/init.c @@ -0,0 +1,378 @@ +static char sccsid[] = "@(#) ./cc1/init.c"; +#include <stdint.h> +#include <stdlib.h> +#include <string.h> + +#include <scc/cstd.h> +#include <scc/scc.h> +#include "cc1.h" + + +typedef struct init Init; + +struct designator { + TINT pos; + Node *expr; + struct designator *next; +}; + +struct init { + TUINT pos; + TUINT max; + struct designator *tail; + struct designator *head; +}; + +static TINT +arydesig(Type *tp, Init *ip) +{ + TINT npos; + Node *np; + + if (tp->op != ARY) + errorp("array index in non-array initializer"); + next(); + np = constexpr(); + npos = np->sym->u.i; + if (npos < 0 || (tp->prop & TDEFINED) && npos >= tp->n.elem) { + errorp("array index in initializer exceeds array bounds"); + npos = 0; + } + freetree(np); + expect(']'); + return npos; +} + +static TINT +fielddesig(Type *tp, Init *ip) +{ + int ons; + Symbol *sym, **p; + + if (!(tp->prop & TAGGREG)) + errorp("field name not in record or union initializer"); + ons = namespace; + namespace = tp->ns; + next(); + namespace = ons; + if (yytoken != IDEN) + unexpected(); + sym = yylval.sym; + next(); + if ((sym->flags & SDECLARED) == 0) { + errorp("unknown field '%s' specified in initializer", + sym->name); + return 0; + } + for (p = tp->p.fields; *p != sym; ++p) + ; + return p - tp->p.fields; +} + +static Init * +init(Init *ip) +{ + ip->tail = ip->head = NULL; + ip->pos = ip->max = 0; + return ip; +} + +static Node * +str2ary(Type *tp) +{ + Node *np; + Type *btp = tp->type;; + Symbol *sym; + size_t len; + char *s; + + np = assign(); + sym = np->left->sym; + if (btp != chartype && btp != uchartype && btp != schartype) { + errorp("array of inappropriate type initialized from string constant"); + return constnode(zero); + } + + len = sym->type->n.elem-1; + if (!(tp->prop & TDEFINED)) { + tp->n.elem = len+1; + deftype(tp); + } else if (tp->n.elem < len) { + warn("initializer-string for array of chars is too long"); + } + + len = tp->n.elem; + s = sym->u.s; + sym = newstring(NULL, len); + strncpy(sym->u.s, s, len); + np->sym = sym; + np->type = sym->type; + + return np; +} + +static Node * +initialize(Type *tp) +{ + Node *np; + Symbol *sym; + + if (tp->op == ARY && yytoken == STRING) + return str2ary(tp); + + if (yytoken == '{' || tp->op == STRUCT || tp->op == ARY) + return initlist(tp); + + np = assign(); + if (eqtype(tp, np->type, 1)) + return np; + + np = convert(decay(np), tp, 0); + if (!np) { + errorp("incorrect initializer"); + return constnode(zero); + } + + return simplify(np); +} + +static Node * +mkcompound(Init *ip, Type *tp) +{ + Node **v, **p; + size_t n; + struct designator *dp, *next; + Symbol *sym; + + if (tp->op == UNION) { + Node *np = NULL; + + v = xmalloc(sizeof(*v)); + for (dp = ip->head; dp; dp = next) { + freetree(np); + np = dp->expr; + next = dp->next; + free(dp); + } + *v = np; + } else { + n = (tp->prop&TDEFINED) ? tp->n.elem : ip->max; + if (n == 0) { + v = NULL; + } else if (n > SIZE_MAX / sizeof(*v)) { + errorp("compound literal too big"); + return constnode(zero); + } else { + n *= sizeof(*v); + v = memset(xmalloc(n), 0, n); + + for (dp = ip->head; dp; dp = next) { + p = &v[dp->pos]; + freetree(*p); + *p = dp->expr; + next = dp->next; + free(dp); + } + } + } + + sym = newsym(NS_IDEN, NULL); + sym->u.init = v; + sym->type = tp; + sym->flags |= SINITLST; + + return constnode(sym); +} + +static void +newdesig(Init *ip, Node *np) +{ + struct designator *dp; + + dp = xmalloc(sizeof(*dp)); + dp->pos = ip->pos; + dp->expr = np; + dp->next = NULL; + + if (ip->head == NULL) { + ip->head = ip->tail = dp; + } else { + ip->tail->next = dp; + ip->tail = dp; + } + + if (ip->pos+1 > ip->max) + ip->max = ip->pos+1; +} + +Node * +initlist(Type *tp) +{ + Init in; + Node *np; + Type *curtp; + int braces, scalar, toomany, outbound; + TINT nelem = tp->n.elem; + static int depth; + + if (depth == NR_SUBTYPE) + error("too many nested initializers"); + ++depth; + init(&in); + braces = scalar = toomany = 0; + + if (accept('{')) + braces = 1; + + do { + curtp = inttype; + switch (yytoken) { + case '[': + in.pos = arydesig(tp, &in); + curtp = tp->type; + goto desig_list; + case '.': + in.pos = fielddesig(tp, &in); + if (in.pos < nelem) + curtp = tp->p.fields[in.pos]->type; + desig_list: + if (yytoken == '[' || yytoken == '.') { + np = initlist(curtp); + goto new_desig; + } + expect('='); + default: + outbound = 0; + + switch (tp->op) { + case ARY: + curtp = tp->type; + if (!(tp->prop & TDEFINED) || in.pos < tp->n.elem) + break; + if (!toomany) + warn("excess elements in array initializer"); + toomany = 1; + outbound = 1; + break; + case UNION: + case STRUCT: + if (in.pos < nelem) { + curtp = tp->p.fields[in.pos]->type; + break; + } + if (!toomany) + warn("excess elements in struct initializer"); + toomany = 1; + outbound = 1; + break; + default: + curtp = tp; + if (!scalar) + warn("braces around scalar initializer"); + scalar = 1; + if (in.pos == 0) + break; + if (!toomany) + warn("excess elements in scalar initializer"); + toomany = 1; + outbound = 1; + break; + } + np = initialize(curtp); + if (outbound) { + freetree(np); + np = NULL; + } + } + +new_desig: + if (np) + newdesig(&in, np); + if (++in.pos == 0) + errorp("compound literal too big"); + if (nelem == in.pos && !braces) + break; + } while (accept(',')); + + if (braces) + expect('}'); + + + if (tp->op == ARY && !(tp->prop & TDEFINED)) { + tp->n.elem = in.max; + deftype(tp); + } + if (in.max == 0) { + errorp("empty braced initializer"); + return constnode(zero); + } + + return mkcompound(&in, tp); +} + +static void +autoinit(Symbol *sym, Node *np) +{ + Symbol *hidden; + Type *tp = sym->type; + size_t n; /* FIXME: It should be SIZET */ + +repeat: + switch (tp->op) { + case UNION: + np = np->sym->u.init[0]; + tp = np->type; + goto repeat; + case ARY: + case STRUCT: + if (!(np->flags & NCONST)) + abort(); /* TODO */ + hidden = newsym(NS_IDEN, NULL); + hidden->type = sym->type; + hidden->flags |= SLOCAL | SHASINIT; + emit(ODECL, hidden); + emit(OINIT, np); + emit(ODECL, sym); + emit(OEXPR, + node(OASSIGN, tp, varnode(sym), varnode(hidden))); + break; + default: + emit(ODECL, sym); + np = node(OASSIGN, tp, varnode(sym), np); + emit(OEXPR, np); + break; + } +} + +void +initializer(Symbol *sym, Type *tp) +{ + Node *np; + int flags = sym->flags; + + if (tp->op == FTN) { + errorp("function '%s' initialized like a variable", + sym->name); + tp = inttype; + } + np = initialize(tp); + + if (flags & SDEFINED) { + errorp("redeclaration of '%s'", sym->name); + } else if ((flags & (SGLOBAL|SLOCAL|SPRIVATE)) != 0) { + if (!(np->flags & NCONST)) { + errorp("initializer element is not constant"); + return; + } + sym->flags |= SHASINIT; + sym->flags &= ~SEMITTED; + emit(ODECL, sym); + emit(OINIT, np); + sym->flags |= SDEFINED; + } else if ((flags & (SEXTERN|STYPEDEF)) != 0) { + errorp("'%s' has both '%s' and initializer", + sym->name, (flags&SEXTERN) ? "extern" : "typedef"); + } else { + autoinit(sym, np); + } +} diff --git a/cc1/ir.md b/src/cc1/ir.md diff --git a/src/cc1/lex.c b/src/cc1/lex.c @@ -0,0 +1,801 @@ +static char sccsid[] = "@(#) ./cc1/lex.c"; +#include <assert.h> +#include <ctype.h> +#include <errno.h> +#include <limits.h> +#include <setjmp.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <scc/cstd.h> +#include <scc/scc.h> +#include "cc1.h" + +int yytoken; +struct yystype yylval; +char yytext[STRINGSIZ+3]; +unsigned short yylen; +int lexmode = CCMODE; +unsigned lineno; +char filenam[FILENAME_MAX]; + +int namespace = NS_IDEN; +static int safe; +Input *input; + +void +ilex(void) +{ + static struct keyword keys[] = { + {"auto", SCLASS, AUTO}, + {"break", BREAK, BREAK}, + {"_Bool", TYPE, BOOL}, + {"__builtin_va_list", TYPE, VA_LIST}, + {"case", CASE, CASE}, + {"char", TYPE, CHAR}, + {"const", TQUALIFIER, CONST}, + {"continue", CONTINUE, CONTINUE}, + {"default", DEFAULT, DEFAULT}, + {"do", DO, DO}, + {"double", TYPE, DOUBLE}, + {"else", ELSE, ELSE}, + {"enum", TYPE, ENUM}, + {"extern", SCLASS, EXTERN}, + {"float", TYPE, FLOAT}, + {"for", FOR, FOR}, + {"goto", GOTO, GOTO}, + {"if", IF, IF}, + {"inline", TQUALIFIER, INLINE}, + {"int", TYPE, INT}, + {"long", TYPE, LONG}, + {"register", SCLASS, REGISTER}, + {"restrict", TQUALIFIER, RESTRICT}, + {"return", RETURN, RETURN}, + {"short", TYPE, SHORT}, + {"signed", TYPE, SIGNED}, + {"sizeof", SIZEOF, SIZEOF}, + {"static", SCLASS, STATIC}, + {"struct", TYPE, STRUCT}, + {"switch", SWITCH, SWITCH}, + {"typedef", SCLASS, TYPEDEF}, + {"union", TYPE, UNION}, + {"unsigned", TYPE, UNSIGNED}, + {"void", TYPE, VOID}, + {"volatile", TQUALIFIER, VOLATILE}, + {"while", WHILE, WHILE}, + {NULL, 0, 0}, + }; + keywords(keys, NS_KEYWORD); +} + +void +setloc(char *fname, unsigned line) +{ + size_t len; + + if ((len = strlen(fname)) >= FILENAME_MAX) + die("cc1: %s: file name too long", fname); + memmove(filenam, fname, len); + filenam[len] = '\0'; + + free(input->filenam); + input->filenam = xstrdup(fname); + lineno = input->lineno = line; +} + +void +addinput(char *fname, Symbol *hide, char *buffer) +{ + FILE *fp; + char *extp; + unsigned flags; + int infileln; + Input *newip, *curip = input; + + if (hide) { + /* this is a macro expansion */ + fp = NULL; + if (hide->hide == UCHAR_MAX) + die("cc1: too many macro expansions"); + ++hide->hide; + flags = IMACRO; + } else if (fname) { + /* a new file */ + if ((fp = fopen(fname, "r")) == NULL) + die("cc1: %s: %s", fname, strerror(errno)); + flags = IFILE; + if (curip && onlyheader) { + infileln = strlen(infile); + if (extp = strrchr(infile, '.')) + infileln -= strlen(extp); + printf("%.*s.o: %s %s\n", + infileln, infile, infile, fname); + } + } else { + /* reading from stdin */ + fp = stdin; + fname = "<stdin>"; + flags = ISTDIN; + } + + newip = xmalloc(sizeof(*newip)); + + if (!buffer) { + buffer = xmalloc(INPUTSIZ); + buffer[0] = '\0'; + } + + if (curip) + curip->lineno = lineno; + + newip->p = newip->begin = newip->line = buffer; + newip->filenam = NULL; + newip->lineno = 0; + newip->next = curip; + newip->fp = fp; + newip->hide = hide; + newip->flags = flags; + input = newip; + + setloc(fname, (curip) ? curip->lineno : newip->lineno); +} + +void +delinput(void) +{ + Input *ip = input; + Symbol *hide = ip->hide; + + switch (ip->flags & ITYPE) { + case IFILE: + if (fclose(ip->fp)) + die("cc1: %s: %s", ip->filenam, strerror(errno)); + break; + case IMACRO: + assert(hide->hide == 1); + --hide->hide; + break; + } + input = ip->next; + free(ip->filenam); + free(ip->line); + if (input) { + lineno = input->lineno; + strcpy(filenam, input->filenam); + } +} + +static void +newline(void) +{ + if (++lineno == 0) + die("cc1: %s: file too long", filenam); +} + +/* + * Read the next character from the input file, counting number of lines + * and joining lines escaped with \ + */ +static int +readchar(void) +{ + FILE *fp = input->fp; + int c; + +repeat: + switch (c = getc(fp)) { + case '\\': + if ((c = getc(fp)) == '\n') { + newline(); + goto repeat; + } + ungetc(c, fp); + c = '\\'; + break; + case '\n': + newline(); + break; + default: + if (!isprint(c) && !ispunct(c) && !isspace(c)) + warn("invalid input character. The shame of UB is yours"); + break; + } + + return c; +} + +/* + * discard a C comment. This function is only called from readline + * because it is impossible to have a comment in a macro, because + * comments are always discarded before processing any cpp directive + */ +static void +comment(int type) +{ + int c; + +repeat: + while ((c = readchar()) != EOF && c != type) + ; + + if (c == EOF) { + errorp("unterminated comment"); + return; + } + + if (type == '*' && (c = readchar()) != '/') + goto repeat; +} + +/* + * readline is used to read a full logic line from a file. + * It discards comments and check that the line fits in + * the input buffer + */ +static int +readline(void) +{ + char *bp, *lim; + int c, peekc = 0; + + if (feof(input->fp)) { + input->flags |= IEOF; + return 0; + } + + *input->line = '\0'; + lim = &input->line[INPUTSIZ-1]; + for (bp = input->line; bp < lim-1; *bp++ = c) { + c = (peekc) ? peekc : readchar(); + peekc = 0; + if (c == '\n' || c == EOF) + break; + if (c != '/') + continue; + + /* check for /* or // */ + peekc = readchar(); + if (peekc != '*' && peekc != '/') + continue; + comment((peekc == '/') ? '\n' : '*'); + peekc = 0; + c = ' '; + } + + input->begin = input->p = input->line; + if (bp == lim-1) { + errorp("line too long"); + --bp; + } + *bp++ = '\n'; + *bp = '\0'; + + return 1; +} + +/* + * moreinput gets more bytes to be passed to the lexer. + * It can take more bytes from macro expansions or + * directly reading from files. When a cpp directive + * is processed the line is discarded because it must not + * be passed to the lexer + */ +static int +moreinput(void) +{ + int wasexpand = 0; + +repeat: + if (!input) + return 0; + + if (*input->p == '\0') { + if ((input->flags&ITYPE) == IMACRO) { + wasexpand = 1; + input->flags |= IEOF; + } + if (input->flags & IEOF) { + delinput(); + goto repeat; + } + if (!readline() || cpp()) { + *input->p = '\0'; + goto repeat; + } + } + + if (onlycpp && !wasexpand) + ppragmaln(); + return 1; +} + +static void +tok2str(void) +{ + if ((yylen = input->p - input->begin) > INTIDENTSIZ) + error("token too big"); + memcpy(yytext, input->begin, yylen); + yytext[yylen] = '\0'; + input->begin = input->p; +} + +static Symbol * +readint(char *s, int base, int sign, Symbol *sym) +{ + Type *tp = sym->type; + struct limits *lim; + TUINT u, val, max; + int c; + + lim = getlimits(tp); + max = lim->max.i; + if (*s == '0') + ++s; + if (toupper(*s) == 'X') + ++s; + + for (u = 0; isxdigit(c = *s++); u = u*base + val) { + static char letters[] = "0123456789ABCDEF"; + val = strchr(letters, toupper(c)) - letters; + repeat: + if (u <= max/base && u*base <= max - val) + continue; + if (tp->prop & TSIGNED) { + if (tp == inttype) + tp = (base==10) ? longtype : uinttype; + else if (tp == longtype) + tp = (base==10) ? llongtype : ulongtype; + else + goto overflow; + } else { + if (tp == uinttype) + tp = (sign==UNSIGNED) ? ulongtype : longtype; + else if (tp == ulongtype) + tp = (sign==UNSIGNED) ? ullongtype : llongtype; + else + goto overflow; + } + sym->type = tp; + lim = getlimits(tp); + max = lim->max.i; + goto repeat; + } + + if (tp->prop & TSIGNED) + sym->u.i = u; + else + sym->u.u = u; + + return sym; + +overflow: + errorp("overflow in integer constant"); + return sym; +} + +static int +integer(char *s, int base) +{ + Type *tp; + Symbol *sym; + unsigned size, sign; + + for (size = sign = 0; ; ++input->p) { + switch (toupper(*input->p)) { + case 'L': + if (size == LLONG) + goto wrong_type; + size = (size == LONG) ? LLONG : LONG; + continue; + case 'U': + if (sign == UNSIGNED) + goto wrong_type; + sign = UNSIGNED; + continue; + default: + goto convert; + wrong_type: + error("invalid suffix in integer constant"); + } + } + +convert: + tp = ctype(INT, sign, size); + sym = newsym(NS_IDEN, NULL); + sym->type = tp; + sym->flags |= SCONSTANT; + yylval.sym = readint(s, base, sign, sym); + return CONSTANT; +} + +static char * +digits(int base) +{ + char *p; + int c; + + for (p = input->p; c = *p; ++p) { + switch (base) { + case 8: + if (!strchr("01234567", c)) + goto end; + break; + case 10: + if (!isdigit(c)) + goto end; + break; + case 16: + if (!isxdigit(c)) + goto end; + break; + } + } +end: + input->p = p; + tok2str(); + return yytext; +} + +static int +number(void) +{ + int base; + + if (*input->p != '0') { + base = 10; + } else { + if (toupper(*++input->p) == 'X') { + ++input->p; + base = 16; + } else { + base = 8; + } + } + + return integer(digits(base), base); +} + +static int +escape(void) +{ + int c, base; + + switch (*++input->p) { + case 'a': return '\a'; + case 'f': return '\f'; + case 'n': return '\n'; + case 'r': return '\r'; + case 't': return '\t'; + case 'v': return '\v'; + case '"': return '"'; + case '\'': return '\''; + case '\\': return '\\'; + case '\?': return '\?'; + case 'u': + /* + * FIXME: universal constants are not correctly handled + */ + if (!isdigit(*++input->p)) + warn("incorrect digit for numerical character constant"); + base = 10; + break; + case 'x': + if (!isxdigit(*++input->p)) + warn("\\x used with no following hex digits"); + base = 16; + break; + case '0': + if (!strchr("01234567", *++input->p)) + warn("\\0 used with no following octal digits"); + base = 8; + break; + default: + warn("unknown escape sequence"); + return ' '; + } + errno = 0; + c = strtoul(input->p, &input->p, base); + if (errno || c > 255) + warn("character constant out of range"); + --input->p; + return c; +} + +static int +character(void) +{ + int c; + Symbol *sym; + + if ((c = *++input->p) == '\\') + c = escape(); + else + c = *input->p; + ++input->p; + if (*input->p != '\'') + errorp("invalid character constant"); + else + ++input->p; + + sym = newsym(NS_IDEN, NULL); + sym->u.i = c; + sym->type = inttype; + yylval.sym = sym; + tok2str(); + return CONSTANT; +} + +static int +string(void) +{ + char *bp = yytext; + int c; + + *bp++ = '"'; + for (++input->p; (c = *input->p) != '"'; ++input->p) { + if (c == '\0') { + errorp("missing terminating '\"' character"); + break; + } + if (c == '\\') + c = escape(); + if (bp == &yytext[STRINGSIZ+1]) { + /* TODO: proper error handling here */ + error("string too long"); + } + *bp++ = c; + } + + input->begin = ++input->p; + *bp = '\0'; + + yylen = bp - yytext + 1; + yylval.sym = newstring(yytext+1, yylen-1); + *bp++ = '"'; + *bp = '\0'; + return STRING; +} + +static int +iden(void) +{ + Symbol *sym; + char *p, *begin; + + begin = input->p; + for (p = begin; isalnum(*p) || *p == '_'; ++p) + ; + input->p = p; + tok2str(); + if ((sym = lookup(NS_CPP, yytext, NOALLOC)) != NULL) { + if (!disexpand && !sym->hide && expand(begin, sym)) + return next(); + } + sym = lookup(namespace, yytext, ALLOC); + yylval.sym = sym; + if (sym->flags & SCONSTANT) + return CONSTANT; + if (sym->token != IDEN) + yylval.token = sym->u.token; + return sym->token; +} + +static int +follow(int expect, int ifyes, int ifno) +{ + if (*input->p++ == expect) + return ifyes; + --input->p; + return ifno; +} + +static int +minus(void) +{ + switch (*input->p++) { + case '-': return DEC; + case '>': return INDIR; + case '=': return SUB_EQ; + default: --input->p; return '-'; + } +} + +static int +plus(void) +{ + switch (*input->p++) { + case '+': return INC; + case '=': return ADD_EQ; + default: --input->p; return '+'; + } +} + +static int +relational(int op, int equal, int shift, int assig) +{ + int c; + + if ((c = *input->p++) == '=') + return equal; + if (c == op) + return follow('=', assig, shift); + --input->p; + return op; +} + +static int +logic(int op, int equal, int logic) +{ + int c; + + if ((c = *input->p++) == '=') + return equal; + if (c == op) + return logic; + --input->p; + return op; +} + +static int +dot(void) +{ + int c; + + if ((c = *input->p) != '.') + return '.'; + if ((c = *++input->p) != '.') + error("incorrect token '..'"); + ++input->p; + return ELLIPSIS; +} + +static int +operator(void) +{ + int t; + + switch (t = *input->p++) { + case '<': t = relational('<', LE, SHL, SHL_EQ); break; + case '>': t = relational('>', GE, SHR, SHR_EQ); break; + case '&': t = logic('&', AND_EQ, AND); break; + case '|': t = logic('|', OR_EQ, OR); break; + case '=': t = follow('=', EQ, '='); break; + case '^': t = follow('=', XOR_EQ, '^'); break; + case '*': t = follow('=', MUL_EQ, '*'); break; + case '/': t = follow('=', DIV_EQ, '/'); break; + case '!': t = follow('=', NE, '!'); break; + case '#': t = follow('#', '$', '#'); break; + case '-': t = minus(); break; + case '+': t = plus(); break; + case '.': t = dot(); break; + } + tok2str(); + return t; +} + +/* TODO: Ensure that namespace is NS_IDEN after a recovery */ + +/* + * skip all the spaces until the next token. When we are in + * CPPMODE \n is not considered a whitespace + */ +static int +skipspaces(void) +{ + int c; + + for (;;) { + switch (c = *input->p) { + case '\n': + if (lexmode == CPPMODE) + goto return_byte; + ++input->p; + case '\0': + if (!moreinput()) + return EOF; + break; + case ' ': + case '\t': + case '\v': + case '\r': + case '\f': + ++input->p; + break; + default: + goto return_byte; + } + } + +return_byte: + input->begin = input->p; + return c; +} + +int +next(void) +{ + int c; + + if ((c = skipspaces()) == EOF) + yytoken = EOFTOK; + else if (isalpha(c) || c == '_') + yytoken = iden(); + else if (isdigit(c)) + yytoken = number(); + else if (c == '"') + yytoken = string(); + else if (c == '\'') + yytoken = character(); + else + yytoken = operator(); + + if (yytoken == EOF) { + strcpy(yytext, "<EOF>"); + if (cppctx) + errorp("#endif expected"); + } + + DBG("TOKEN %s", yytext); + return yytoken; +} + +void +expect(int tok) +{ + if (yytoken != tok) { + if (isgraph(tok)) + errorp("expected '%c' before '%s'", tok, yytext); + else + errorp("unexpected '%s'", yytext); + } else { + next(); + } +} + +int +ahead(void) +{ + skipspaces(); + return *input->begin; +} + +void +setsafe(int type) +{ + safe = type; +} + +void +discard(void) +{ + extern jmp_buf recover; + int c; + + input->begin = input->p; + for (c = yytoken; ; c = *input->begin++) { + switch (safe) { + case END_COMP: + if (c == '}') + goto jump; + goto semicolon; + case END_COND: + if (c == ')') + goto jump; + break; + case END_LDECL: + if (c == ',') + goto jump; + case END_DECL: + semicolon: + if (c == ';') + goto jump; + break; + } + if (c == '\0' && !moreinput()) + exit(1); + } +jump: + yytoken = c; + longjmp(recover, 1); +} diff --git a/src/cc1/main.c b/src/cc1/main.c @@ -0,0 +1,102 @@ +static char sccsid[] = "@(#) ./cc1/main.c"; +#include <setjmp.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> + +#include <scc/arg.h> +#include <scc/scc.h> +#include "cc1.h" + +char *argv0, *infile; + +int warnings; +jmp_buf recover; + +static struct items uflags; +int onlycpp, onlyheader; + + +extern int failure; + +static void +defmacro(char *macro) +{ + char *p = strchr(macro, '='); + + if (p) + *p++ = '\0'; + else + p = "1"; + + defdefine(macro, p, "command-line"); +} + +static void +usage(void) +{ + fputs("usage: cc1 [-Ewd] [-D def[=val]]... [-U def]... " + "[-I dir]... [-o output] [input]\n", stderr); + exit(1); +} + +int +main(int argc, char *argv[]) +{ + int i; + + ilex(); + icpp(); + icode(); + ibuilts(); + + ARGBEGIN { + case 'D': + defmacro(EARGF(usage())); + break; + case 'M': + onlyheader = 1; + break; + case 'E': + onlycpp = 1; + break; + case 'I': + incdir(EARGF(usage())); + break; + case 'U': + newitem(&uflags, EARGF(usage())); + break; + case 'd': + DBGON(); + break; + case 'w': + warnings = 1; + break; + default: + usage(); + } ARGEND + + if (argc > 1) + usage(); + + for (i = 0; i < uflags.n; ++i) + undefmacro(uflags.s[i]); + + infile = (*argv) ? *argv : "<stdin>"; + addinput(*argv, NULL, NULL); + + /* + * we cannot initialize arch until we have an + * output stream, because we maybe want to emit new types + */ + iarch(); + if (onlycpp || onlyheader) { + outcpp(); + } else { + for (next(); yytoken != EOFTOK; decl()) + ; + } + + return failure; +} diff --git a/src/cc1/stmt.c b/src/cc1/stmt.c @@ -0,0 +1,386 @@ +static char sccsid[] = "@(#) ./cc1/stmt.c"; +#include <stddef.h> +#include <setjmp.h> + +#include <scc/cstd.h> +#include <scc/scc.h> +#include "cc1.h" + +#define NEGATE 1 +#define NONEGATE 0 + +Symbol *curfun; + +static void stmt(Symbol *lbreak, Symbol *lcont, Switch *lswitch); + +static void +label(void) +{ + Symbol *sym; + + switch (yytoken) { + case IDEN: + case TYPEIDEN: + sym = lookup(NS_LABEL, yytext, ALLOC); + if (sym->flags & SDEFINED) + error("label '%s' already defined", yytext); + if ((sym->flags & SDECLARED) == 0) + sym = install(NS_LABEL, sym); + sym->flags |= SDEFINED; + emit(OLABEL, sym); + next(); + expect(':'); + break; + default: + unexpected(); + } +} + +static void +stmtexp(Symbol *lbreak, Symbol *lcont, Switch *lswitch) +{ + Node *np; + + if (accept(';')) + return; + if (yytoken == IDEN && ahead() == ':') { + label(); + stmt(lbreak, lcont, lswitch); + return; + } + np = expr(); + if ((np->flags & NEFFECT) == 0) + warn("expression without side effects"); + emit(OEXPR, np); + expect(';'); +} + +static Node * +condition(int neg) +{ + Node *np; + + expect('('); + np = condexpr(neg); + expect(')'); + + return np; +} + +static void +While(Symbol *lbreak, Symbol *lcont, Switch *lswitch) +{ + Symbol *begin; + Node *np; + + begin = newlabel(); + lcont = newlabel(); + lbreak = newlabel(); + + expect(WHILE); + np = condition(NONEGATE); + + emit(OJUMP, lcont); + + emit(OBLOOP, NULL); + emit(OLABEL, begin); + stmt(lbreak, lcont, lswitch); + emit(OLABEL, lcont); + emit(OBRANCH, begin); + emit(OEXPR, np); + emit(OELOOP, NULL); + + emit(OLABEL, lbreak); +} + +static void +For(Symbol *lbreak, Symbol *lcont, Switch *lswitch) +{ + Symbol *begin, *cond; + Node *econd, *einc; + + begin = newlabel(); + lcont = newlabel(); + cond = newlabel(); + lbreak = newlabel(); + + pushctx(); + + expect(FOR); + expect('('); + switch (yytoken) { + case TYPE: + case TYPEIDEN: + case TQUALIFIER: + case SCLASS: + decl(); + break; + default: + emit(OEXPR, expr()); + case ';': + expect(';'); + break; + } + econd = (yytoken != ';') ? condexpr(NONEGATE) : NULL; + expect(';'); + einc = (yytoken != ')') ? expr() : NULL; + expect(')'); + + emit(OJUMP, cond); + + emit(OBLOOP, NULL); + emit(OLABEL, begin); + stmt(lbreak, lcont, lswitch); + emit(OLABEL, lcont); + emit(OEXPR, einc); + emit(OLABEL, cond); + emit((econd) ? OBRANCH : OJUMP, begin); + emit(OEXPR, econd); + emit(OELOOP, NULL); + + emit(OLABEL, lbreak); + + popctx(); +} + +static void +Dowhile(Symbol *lbreak, Symbol *lcont, Switch *lswitch) +{ + Symbol *begin; + Node *np; + + begin = newlabel(); + lcont = newlabel(); + lbreak = newlabel(); + + expect(DO); + + emit(OBLOOP, NULL); + emit(OLABEL, begin); + stmt(lbreak, lcont, lswitch); + expect(WHILE); + np = condition(NONEGATE); + emit(OLABEL, lcont); + emit(OBRANCH, begin); + emit(OEXPR, np); + emit(OELOOP, NULL); + + emit(OLABEL, lbreak); +} + +static void +Return(Symbol *lbreak, Symbol *lcont, Switch *lswitch) +{ + Node *np; + Type *tp = curfun->type->type; + + expect(RETURN); + np = (yytoken != ';') ? decay(expr()) : NULL; + expect(';'); + if (!np) { + if (tp != voidtype) + warn("function returning non void returns no value"); + tp = voidtype; + } else if (np->type != tp) { + if (tp == voidtype) + warn("function returning void returns a value"); + else if ((np = convert(np, tp, 0)) == NULL) + errorp("incorrect type in return"); + } + emit(ORET, NULL); + emit(OEXPR, np); +} + +static void +Break(Symbol *lbreak, Symbol *lcont, Switch *lswitch) +{ + expect(BREAK); + if (!lbreak) { + errorp("break statement not within loop or switch"); + } else { + emit(OJUMP, lbreak); + expect(';'); + } +} + +static void +Continue(Symbol *lbreak, Symbol *lcont, Switch *lswitch) +{ + expect(CONTINUE); + if (!lcont) { + errorp("continue statement not within loop"); + } else { + emit(OJUMP, lcont); + expect(';'); + } +} + +static void +Goto(Symbol *lbreak, Symbol *lcont, Switch *lswitch) +{ + Symbol *sym; + + namespace = NS_LABEL; + next(); + namespace = NS_IDEN; + + if (yytoken != IDEN) + unexpected(); + sym = yylval.sym; + if ((sym->flags & SDECLARED) == 0) + sym = install(NS_LABEL, sym); + sym->flags |= SUSED; + emit(OJUMP, sym); + next(); + expect(';'); +} + +static void +Swtch(Symbol *obr, Symbol *lcont, Switch *osw) +{ + Switch sw = {0}; + Node *cond; + Symbol *lbreak; + + expect(SWITCH); + + expect ('('); + if ((cond = convert(expr(), inttype, 0)) == NULL) { + errorp("incorrect type in switch statement"); + cond = constnode(zero); + } + expect (')'); + + lbreak = newlabel(); + emit(OBSWITCH, NULL); + emit(OEXPR, cond); + stmt(lbreak, lcont, &sw); + emit(OESWITCH, lbreak); + emit(OLABEL, lbreak); +} + +static void +Case(Symbol *lbreak, Symbol *lcont, Switch *sw) +{ + Node *np; + Symbol *label; + + expect(CASE); + if ((np = constexpr()) == NULL) + errorp("case label does not reduce to an integer constant"); + if (!sw) { + errorp("case label not within a switch statement"); + } else if (sw->nr >= 0 && ++sw->nr == NR_SWITCH) { + errorp("too many case labels for a switch statement"); + sw->nr = -1; + } + expect(':'); + + label = newlabel(); + emit(OCASE, label); + emit(OEXPR, np); + emit(OLABEL, label); + stmt(lbreak, lcont, sw); +} + +static void +Default(Symbol *lbreak, Symbol *lcont, Switch *sw) +{ + Symbol *label = newlabel(); + + if (sw->hasdef) + errorp("multiple default labels in one switch"); + sw->hasdef = 1; + expect(DEFAULT); + expect(':'); + emit(ODEFAULT, label); + emit(OLABEL, label); + stmt(lbreak, lcont, sw); +} + +static void +If(Symbol *lbreak, Symbol *lcont, Switch *lswitch) +{ + Symbol *end, *lelse; + Node *np; + + lelse = newlabel(); + expect(IF); + np = condition(NEGATE); + emit(OBRANCH, lelse); + emit(OEXPR, np); + stmt(lbreak, lcont, lswitch); + if (accept(ELSE)) { + end = newlabel(); + emit(OJUMP, end); + emit(OLABEL, lelse); + stmt(lbreak, lcont, lswitch); + emit(OLABEL, end); + } else { + emit(OLABEL, lelse); + } +} + +static void +blockit(Symbol *lbreak, Symbol *lcont, Switch *lswitch) +{ + switch (yytoken) { + case TYPEIDEN: + if (ahead() == ':') + goto parse_stmt; + case TYPE: + case TQUALIFIER: + case SCLASS: + decl(); + return; + default: + parse_stmt: + stmt(lbreak, lcont, lswitch); + } +} + +void +compound(Symbol *lbreak, Symbol *lcont, Switch *lswitch) +{ + static int nested; + + pushctx(); + expect('{'); + + if (nested == NR_BLOCK) + error("too many nesting levels of compound statements"); + + ++nested; + for (;;) { + if (yytoken == '}') + break; + blockit(lbreak, lcont, lswitch); + } + --nested; + + popctx(); + expect('}'); +} + +static void +stmt(Symbol *lbreak, Symbol *lcont, Switch *lswitch) +{ + void (*fun)(Symbol *, Symbol *, Switch *); + + switch (yytoken) { + case '{': fun = compound; break; + case RETURN: fun = Return; break; + case WHILE: fun = While; break; + case FOR: fun = For; break; + case DO: fun = Dowhile; break; + case IF: fun = If; break; + case BREAK: fun = Break; break; + case CONTINUE: fun = Continue; break; + case GOTO: fun = Goto; break; + case SWITCH: fun = Swtch; break; + case CASE: fun = Case; break; + case DEFAULT: fun = Default; break; + default: fun = stmtexp; break; + } + (*fun)(lbreak, lcont, lswitch); +} diff --git a/src/cc1/symbol.c b/src/cc1/symbol.c @@ -0,0 +1,353 @@ +static char sccsid[] = "@(#) ./cc1/symbol.c"; +#include <assert.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <scc/cstd.h> +#include <scc/scc.h> +#include "cc1.h" + +#define NR_SYM_HASH 64 +#define NR_CPP_HASH 32 +#define NR_LBL_HASH 16 + +unsigned curctx; +static unsigned short counterid; + +static Symbol *head, *labels; +static Symbol *htab[NR_SYM_HASH]; +static Symbol *htabcpp[NR_CPP_HASH]; +static Symbol *htablbl[NR_LBL_HASH]; + +#ifndef NDEBUG +void +dumpstab(Symbol **tbl, char *msg) +{ + Symbol **bp, *sym; + unsigned size; + + fprintf(stderr, "Symbol Table dump at ctx=%u\n%s\n", curctx, msg); + if (tbl == htab) + size = NR_SYM_HASH; + else if (tbl == htabcpp) + size = NR_CPP_HASH; + else if (tbl == htablbl) + size = NR_LBL_HASH; + else + abort(); + + for (bp = tbl; bp < &tbl[size]; ++bp) { + if (*bp == NULL) + continue; + fprintf(stderr, "%d", (int) (bp - htab)); + for (sym = *bp; sym; sym = sym->hash) + fprintf(stderr, "->[%d,%d:'%s'=%p]", + sym->ns, sym->ctx, sym->name, (void *) sym); + putc('\n', stderr); + } + fputs("head:", stderr); + for (sym = head; sym; sym = sym->next) { + fprintf(stderr, "->[%d,%d:'%s'=%p]", + sym->ns, sym->ctx, + (sym->name) ? sym->name : "", (void *) sym); + } + fputs("\nlabels:", stderr); + for (sym = labels; sym; sym = sym->next) { + fprintf(stderr, "->[%d,%d:'%s'=%p]", + sym->ns, sym->ctx, + (sym->name) ? sym->name : "", (void *) sym); + } + putc('\n', stderr); +} +#endif + +static Symbol ** +hash(char *s, int ns) +{ + unsigned c, h, size; + Symbol **tab; + + for (h = 0; c = *s; ++s) + h = h*33 ^ c; + + switch (ns) { + case NS_CPP: + tab = htabcpp; + size = NR_CPP_HASH-1; + break; + case NS_LABEL: + tab = htablbl; + size = NR_LBL_HASH-1; + break; + default: + tab = htab; + size = NR_SYM_HASH-1; + break; + } + return &tab[h & size]; +} + +static void +unlinkhash(Symbol *sym) +{ + Symbol **h; + + if ((sym->flags & SDECLARED) == 0) + return; + h = hash(sym->name, sym->ns); + assert(sym->ns == NS_CPP || *h == sym); + while (*h != sym) + h = &(*h)->hash; + *h = sym->hash; +} + +void +pushctx(void) +{ + DBG("SYM: pushed context %d", curctx+1); + if (++curctx == NR_BLOCK+1) + error("too many nested blocks"); +} + +void +killsym(Symbol *sym) +{ + short f; + char *name; + + if (!sym) + return; + f = sym->flags; + if (f & SSTRING) + free(sym->u.s); + if (sym->ns == NS_TAG) + sym->type->prop &= ~TDEFINED; + unlinkhash(sym); + if ((name = sym->name) != NULL) { + switch (sym->ns) { + case NS_LABEL: + if ((f & SDEFINED) == 0) + errorp("label '%s' is not defined", name); + case NS_IDEN: + if ((f & (SUSED|SGLOBAL|SDECLARED)) == SDECLARED) + warn("'%s' defined but not used", name); + break; + } + } + free(name); + free(sym); +} + +void +popctx(void) +{ + Symbol *next, *sym; + int ns, dangling = 0; + + DBG("SYM: poped context %d", curctx); + /* + * we have to be careful before popping the current + * context, because since the parser is one token + * ahead it may already have read an identifier at + * this point, and yylval.sym is a pointer to + * the symbol associated to such token. If that + * symbol is from the context that we are popping + * then we are going to generate a dangling pointer. + * We can detect this situation and call again to + * lookup. + */ + if ((yytoken == IDEN || yytoken == TYPEIDEN) && + yylval.sym->ctx == curctx) { + ns = yylval.sym->ns; + dangling = 1; + } + + for (sym = head; sym && sym->ctx == curctx; sym = next) { + /* + * Since we are unlinking them in the inverse order + * we do know that sym is always the head of the + * collision list + */ + next = sym->next; + killsym(sym); + } + head = sym; + + if (--curctx == GLOBALCTX) { + for (sym = labels; sym; sym = next) { + next = sym->next; + killsym(sym); + } + labels = NULL; + } + + if (dangling) { + yylval.sym = lookup(ns, yytext, ALLOC); + yytoken = yylval.sym->token; + } +} + +unsigned +newid(void) +{ + unsigned short id; + + if (lexmode == CPPMODE) + return 0; + id = ++counterid; + if (id == 0) { + die("cc1: overflow in %s identifiers", + (curctx) ? "internal" : "external"); + } + return id; +} + +Symbol * +newsym(int ns, char *name) +{ + Symbol *sym; + + sym = xmalloc(sizeof(*sym)); + if (name) + name = xstrdup(name); + sym->name = name; + sym->id = 0; + sym->hide = 0; + sym->ns = ns; + sym->ctx = curctx; + sym->token = IDEN; + sym->flags = 0; + sym->u.s = NULL; + sym->type = NULL; + sym->hash = NULL; + + if (ns == NS_LABEL) { + sym->next = labels; + labels = sym; + } else if (ns != NS_CPP) { + sym->next = head; + head = sym; + } + return sym; +} + +static Symbol * +linkhash(Symbol *sym) +{ + Symbol **h; + + h = hash(sym->name, sym->ns); + sym->hash = *h; + *h = sym; + + if (sym->ns != NS_CPP) + sym->id = newid(); + sym->flags |= SDECLARED; + return sym; +} + +Symbol * +newstring(char *s, size_t len) +{ + Symbol *sym = newsym(NS_IDEN, NULL); + + if (lexmode != CPPMODE) + sym->type = mktype(chartype, ARY, len, NULL); + sym->id = newid(); + sym->flags |= SSTRING | SCONSTANT | SPRIVATE; + sym->u.s = xmalloc(len); + if (s) + memcpy(sym->u.s, s, len); + + return sym; +} + +Symbol * +newlabel(void) +{ + Symbol *sym = newsym(NS_LABEL, NULL); + sym->id = newid(); + return sym; +} + +Symbol * +lookup(int ns, char *name, int alloc) +{ + Symbol *sym; + int sns, c; + char *t; + + c = *name; + for (sym = *hash(name, ns); sym; sym = sym->hash) { + t = sym->name; + if (*t != c || strcmp(t, name)) + continue; + sns = sym->ns; + if (sns == ns) + return sym; + /* + * When a lookup is done in a namespace associated + * to a struct we also want symbols of NS_IDEN which + * are typedef, because in other case we cannot declare + * fields of such types. + * TODO: Remove this trick + */ + if (sns == NS_KEYWORD || + (sym->flags & STYPEDEF) && ns >= NS_STRUCTS) { + return sym; + } + } + return (alloc == ALLOC) ? newsym(ns, name) : NULL; +} + +Symbol * +install(int ns, Symbol *sym) +{ + if (sym->flags & SDECLARED || sym->ctx != curctx) { + if (sym->ctx == curctx && ns == sym->ns) + return NULL; + sym = newsym(ns, sym->name); + } + return linkhash(sym); +} + +void +keywords(struct keyword *key, int ns) +{ + Symbol *sym; + + for ( ; key->str; ++key) { + sym = linkhash(newsym(ns, key->str)); + sym->token = key->token; + sym->u.token = key->value; + } + /* + * Remove all the predefined symbols from * the symbol list. It + * will make faster some operations. There is no problem of memory + * leakeage because this memory is not ever freed + */ + counterid = 0; + head = NULL; +} + +void +builtins(struct builtin *built) +{ + Symbol *sym; + struct builtin *bp; + + for (bp = built; bp->str; ++bp) { + sym = linkhash(newsym(NS_KEYWORD, bp->str)); + sym->token = BUILTIN; + sym->u.fun = bp->fun; + } + /* + * Remove all the predefined symbols from * the symbol list. It + * will make faster some operations. There is no problem of memory + * leakeage because this memory is not ever freed + */ + counterid = 0; + head = NULL; +} diff --git a/src/cc1/target/amd64-sysv/arch.c b/src/cc1/target/amd64-sysv/arch.c @@ -0,0 +1,220 @@ +static char sccsid[] = "@(#) ./cc1/arch/amd64-sysv/arch.c"; + +#include <scc/scc.h> +#include "../../cc1.h" + +#define RANK_BOOL 0 +#define RANK_SCHAR 1 +#define RANK_UCHAR 1 +#define RANK_CHAR 1 +#define RANK_SHORT 2 +#define RANK_USHORT 2 +#define RANK_INT 3 +#define RANK_UINT 3 +#define RANK_LONG 4 +#define RANK_ULONG 4 +#define RANK_LLONG 5 +#define RANK_ULLONG 5 +#define RANK_FLOAT 6 +#define RANK_DOUBLE 7 +#define RANK_LDOUBLE 8 + +/* + * Initializaion of type pointers were done with + * a C99 initilizator '... = &(Type) {...', but + * c compiler in Plan9 gives error with this + * syntax, so I have switched it to this ugly form + * I hope I will change it again in the future + */ + +static Type types[] = { + { /* 0 = voidtype */ + .op = VOID, + .letter = L_VOID, + }, + { /* 1 = pvoidtype */ + .op = PTR, + .letter = L_POINTER, + .prop = TDEFINED, + .type = &types[5], /* chartype */ + .size = 8, + .align = 8, + }, + { /* 2 = booltype */ + .op = INT, + .letter = L_BOOL, + .prop = TDEFINED | TINTEGER | TARITH, + .size = 1, + .align = 1, + .n.rank = RANK_BOOL, + }, + { /* 3 = schartype */ + .op = INT, + .letter = L_INT8, + .prop = TDEFINED | TINTEGER | TARITH | TSIGNED, + .size = 1, + .align = 1, + .n.rank = RANK_SCHAR, + }, + { /* 4 = uchartype */ + .op = INT, + .letter = L_UINT8, + .prop = TDEFINED | TINTEGER | TARITH, + .size = 1, + .align = 1, + .n.rank = RANK_UCHAR, + }, + { /* 5 = chartype */ + .op = INT, + .letter = L_INT8, + .prop = TDEFINED | TINTEGER | TARITH | TSIGNED, + .size = 1, + .align = 1, + .n.rank = RANK_CHAR, + }, + { /* 6 = ushortype */ + .op = INT, + .letter = L_UINT16, + .prop = TDEFINED | TINTEGER | TARITH, + .size = 2, + .align = 2, + .n.rank = RANK_USHORT, + }, + { /* 7 = shortype */ + .op = INT, + .letter = L_INT16, + .prop = TDEFINED | TINTEGER | TARITH | TSIGNED, + .size = 2, + .align = 2, + .n.rank = RANK_SHORT, + }, + { /* 8 = uinttype */ + .op = INT, + .letter = L_UINT32, + .prop = TDEFINED | TINTEGER | TARITH, + .size = 4, + .align = 4, + .n.rank = RANK_UINT, + }, + { /* 9 = inttype */ + .op = INT, + .letter = L_INT32, + .prop = TDEFINED | TINTEGER | TARITH | TSIGNED, + .size = 4, + .align = 4, + .n.rank = RANK_INT, + }, + { /* 10 = longtype */ + .op = INT, + .letter = L_INT64, + .prop = TDEFINED | TINTEGER | TARITH | TSIGNED, + .size = 8, + .align = 8, + .n.rank = RANK_LONG, + }, + { /* 11 = ulongtype */ + .op = INT, + .letter = L_UINT64, + .prop = TDEFINED | TINTEGER | TARITH, + .size = 8, + .align = 8, + .n.rank = RANK_ULONG, + }, + { /* 12 = ullongtype */ + .op = INT, + .letter = L_UINT64, + .prop = TDEFINED | TINTEGER | TARITH, + .size = 8, + .align = 8, + .n.rank = RANK_ULLONG, + }, + { /* 13 = llongtype */ + .op = INT, + .letter = L_INT64, + .prop = TDEFINED | TINTEGER | TARITH | TSIGNED, + .size = 8, + .align = 8, + .n.rank = RANK_LLONG, + }, + { /* 14 = floattype */ + .op = FLOAT, + .letter = L_FLOAT, + .prop = TDEFINED | TARITH, + .size = 4, + .align = 4, + .n.rank = RANK_FLOAT, + }, + { /* 15 = doubletype */ + .op = FLOAT, + .letter = L_DOUBLE, + .prop = TDEFINED | TARITH, + .size = 8, + .align = 8, + .n.rank = RANK_DOUBLE, + }, + { /* 16 = ldoubletype */ + .op = FLOAT, + .letter = L_LDOUBLE, + .prop = TDEFINED | TARITH, + .size = 16, + .align = 16, + .n.rank = RANK_LDOUBLE, + }, + { /* 17 = sizettype */ + .op = INT, + .letter = L_UINT64, + .prop = TDEFINED | TINTEGER | TARITH, + .size = 8, + .align = 8, + .n.rank = RANK_UINT, + }, + { /* 18 = ellipsis */ + .op = ELLIPSIS, + .letter = L_ELLIPSIS, + .prop = TDEFINED, + }, + { /* 19 = pdifftype */ + .op = INT, + .letter = L_INT64, + .prop = TDEFINED | TINTEGER | TARITH | TSIGNED, + .size = 8, + .align = 8, + .n.rank = RANK_LONG, + }, + { /* 20 = va_type */ + .op = STRUCT, + .letter = L_VA_ARG, + .prop = TDEFINED, + .size = 24, + .align = 8, + }, +}; + +Type *voidtype = &types[0], *pvoidtype = &types[1], + *booltype = &types[2], *schartype = &types[3], + *uchartype = &types[4], *chartype = &types[5], + *ushortype = &types[6], *shortype = &types[7], + *uinttype = &types[8], *inttype = &types[9], + *longtype = &types[10], *ulongtype = &types[11], + *ullongtype = &types[12], *llongtype = &types[13], + *floattype = &types[14], *doubletype = &types[15], + *ldoubletype = &types[16], + *sizettype = &types[17], *pdifftype = &types[19], + *ellipsistype = &types[18], *va_type = &types[20], + *va_list_type; + +static Symbol dummy0 = {.u.i = 0, .type = &types[9]}, + dummy1 = {.u.i = 1, .type = &types[9]}; +Symbol *zero = &dummy0, *one = &dummy1; + +void +iarch(void) +{ + va_list_type = mktype(va_type, ARY, 1, NULL); +} + +int +valid_va_list(Type *tp) +{ + return tp->op == PTR && eqtype(tp->type, va_type, 1); +} diff --git a/src/cc1/target/amd64-sysv/arch.mk b/src/cc1/target/amd64-sysv/arch.mk @@ -0,0 +1,4 @@ +OBJ-amd64-sysv= $(OBJS) target/amd64-sysv/arch.o + +$(LIBEXEC)/cc1-amd64-sysv: $(OBJ-amd64-sysv) + $(CC) $(SCC_LDFLAGS) $(OBJ-amd64-sysv) -lscc -o $@ diff --git a/src/cc1/target/arm64-sysv/arch.c b/src/cc1/target/arm64-sysv/arch.c @@ -0,0 +1,220 @@ +static char sccsid[] = "@(#) ./cc1/arch/arm64-sysv/arch.c"; + +#include <scc/scc.h> +#include "../../cc1.h" + +#define RANK_BOOL 0 +#define RANK_SCHAR 1 +#define RANK_UCHAR 1 +#define RANK_CHAR 1 +#define RANK_SHORT 2 +#define RANK_USHORT 2 +#define RANK_INT 3 +#define RANK_UINT 3 +#define RANK_LONG 4 +#define RANK_ULONG 4 +#define RANK_LLONG 5 +#define RANK_ULLONG 5 +#define RANK_FLOAT 6 +#define RANK_DOUBLE 7 +#define RANK_LDOUBLE 8 + +/* + * Initializaion of type pointers were done with + * a C99 initilizator '... = &(Type) {...', but + * c compiler in Plan9 gives error with this + * syntax, so I have switched it to this ugly form + * I hope I will change it again in the future + */ + +static Type types[] = { + { /* 0 = voidtype */ + .op = VOID, + .letter = L_VOID, + }, + { /* 1 = pvoidtype */ + .op = PTR, + .letter = L_POINTER, + .prop = TDEFINED, + .type = &types[5], /* chartype */ + .size = 8, + .align = 8, + }, + { /* 2 = booltype */ + .op = INT, + .letter = L_BOOL, + .prop = TDEFINED | TINTEGER | TARITH, + .size = 1, + .align = 1, + .n.rank = RANK_BOOL, + }, + { /* 3 = schartype */ + .op = INT, + .letter = L_INT8, + .prop = TDEFINED | TINTEGER | TARITH | TSIGNED, + .size = 1, + .align = 1, + .n.rank = RANK_SCHAR, + }, + { /* 4 = uchartype */ + .op = INT, + .letter = L_UINT8, + .prop = TDEFINED | TINTEGER | TARITH, + .size = 1, + .align = 1, + .n.rank = RANK_UCHAR, + }, + { /* 5 = chartype */ + .op = INT, + .letter = L_INT8, + .prop = TDEFINED | TINTEGER | TARITH | TSIGNED, + .size = 1, + .align = 1, + .n.rank = RANK_CHAR, + }, + { /* 6 = ushortype */ + .op = INT, + .letter = L_UINT16, + .prop = TDEFINED | TINTEGER | TARITH, + .size = 2, + .align = 2, + .n.rank = RANK_USHORT, + }, + { /* 7 = shortype */ + .op = INT, + .letter = L_INT16, + .prop = TDEFINED | TINTEGER | TARITH | TSIGNED, + .size = 2, + .align = 2, + .n.rank = RANK_SHORT, + }, + { /* 8 = uinttype */ + .op = INT, + .letter = L_UINT32, + .prop = TDEFINED | TINTEGER | TARITH, + .size = 4, + .align = 4, + .n.rank = RANK_UINT, + }, + { /* 9 = inttype */ + .op = INT, + .letter = L_INT32, + .prop = TDEFINED | TINTEGER | TARITH | TSIGNED, + .size = 4, + .align = 4, + .n.rank = RANK_INT, + }, + { /* 10 = longtype */ + .op = INT, + .letter = L_INT64, + .prop = TDEFINED | TINTEGER | TARITH | TSIGNED, + .size = 8, + .align = 8, + .n.rank = RANK_LONG, + }, + { /* 11 = ulongtype */ + .op = INT, + .letter = L_UINT64, + .prop = TDEFINED | TINTEGER | TARITH, + .size = 8, + .align = 8, + .n.rank = RANK_ULONG, + }, + { /* 12 = ullongtype */ + .op = INT, + .letter = L_UINT64, + .prop = TDEFINED | TINTEGER | TARITH, + .size = 8, + .align = 8, + .n.rank = RANK_ULLONG, + }, + { /* 13 = llongtype */ + .op = INT, + .letter = L_INT64, + .prop = TDEFINED | TINTEGER | TARITH | TSIGNED, + .size = 8, + .align = 8, + .n.rank = RANK_LLONG, + }, + { /* 14 = floattype */ + .op = FLOAT, + .letter = L_FLOAT, + .prop = TDEFINED | TARITH, + .size = 4, + .align = 4, + .n.rank = RANK_FLOAT, + }, + { /* 15 = doubletype */ + .op = FLOAT, + .letter = L_DOUBLE, + .prop = TDEFINED | TARITH, + .size = 8, + .align = 8, + .n.rank = RANK_DOUBLE, + }, + { /* 16 = ldoubletype */ + .op = FLOAT, + .letter = L_LDOUBLE, + .prop = TDEFINED | TARITH, + .size = 16, + .align = 16, + .n.rank = RANK_LDOUBLE, + }, + { /* 17 = sizettype */ + .op = INT, + .letter = L_UINT64, + .prop = TDEFINED | TINTEGER | TARITH, + .size = 8, + .align = 8, + .n.rank = RANK_UINT, + }, + { /* 18 = ellipsis */ + .op = ELLIPSIS, + .letter = L_ELLIPSIS, + .prop = TDEFINED, + }, + { /* 19 = pdifftype */ + .op = INT, + .letter = L_INT64, + .prop = TDEFINED | TINTEGER | TARITH | TSIGNED, + .size = 8, + .align = 8, + .n.rank = RANK_LONG, + }, + { /* 20 = va_type */ + .op = STRUCT, + .letter = L_VA_ARG, + .prop = TDEFINED, + .size = 24, + .align = 8, + }, +}; + +Type *voidtype = &types[0], *pvoidtype = &types[1], + *booltype = &types[2], *schartype = &types[3], + *uchartype = &types[4], *chartype = &types[5], + *ushortype = &types[6], *shortype = &types[7], + *uinttype = &types[8], *inttype = &types[9], + *longtype = &types[10], *ulongtype = &types[11], + *ullongtype = &types[12], *llongtype = &types[13], + *floattype = &types[14], *doubletype = &types[15], + *ldoubletype = &types[16], + *sizettype = &types[17], *pdifftype = &types[19], + *ellipsistype = &types[18], *va_type = &types[20], + *va_list_type; + +static Symbol dummy0 = {.u.i = 0, .type = &types[9]}, + dummy1 = {.u.i = 1, .type = &types[9]}; +Symbol *zero = &dummy0, *one = &dummy1; + +void +iarch(void) +{ + va_list_type = mktype(va_type, ARY, 1, NULL); +} + +int +valid_va_list(Type *tp) +{ + return tp->op == PTR && eqtype(tp->type, va_type, 1); +} diff --git a/src/cc1/target/arm64-sysv/arch.mk b/src/cc1/target/arm64-sysv/arch.mk @@ -0,0 +1,4 @@ +OBJ-arm64-sysv= $(OBJS) target/arm64-sysv/arch.o + +$(LIBEXEC)/cc1-arm64-sysv: $(OBJ-arm64-sysv) + $(CC) $(SCC_LDFLAGS) $(OBJ-arm64-sysv) -lscc -o $@ diff --git a/src/cc1/target/i386-sysv/arch.c b/src/cc1/target/i386-sysv/arch.c @@ -0,0 +1,221 @@ +static char sccsid[] = "@(#) ./cc1/arch/i386-sysv/arch.c"; + +#include <scc/scc.h> +#include "../../cc1.h" + +#define RANK_BOOL 0 +#define RANK_SCHAR 1 +#define RANK_UCHAR 1 +#define RANK_CHAR 1 +#define RANK_SHORT 2 +#define RANK_USHORT 2 +#define RANK_INT 3 +#define RANK_UINT 3 +#define RANK_LONG 4 +#define RANK_ULONG 4 +#define RANK_LLONG 5 +#define RANK_ULLONG 5 +#define RANK_FLOAT 6 +#define RANK_DOUBLE 7 +#define RANK_LDOUBLE 8 + +/* + * Initializaion of type pointers were done with + * a C99 initilizator '... = &(Type) {...', but + * c compiler in Plan9 gives error with this + * syntax, so I have switched it to this ugly form + * I hope I will change it again in the future + */ + +static Type types[] = { + { /* 0 = voidtype */ + .op = VOID, + .letter = L_VOID, + }, + { /* 1 = pvoidtype */ + .op = PTR, + .letter = L_POINTER, + .prop = TDEFINED, + .type = &types[5], /* chartype */ + .size = 4, + .align = 4, + }, + { /* 2 = booltype */ + .op = INT, + .letter = L_BOOL, + .prop = TDEFINED | TINTEGER | TARITH, + .size = 1, + .align = 1, + .n.rank = RANK_BOOL, + }, + { /* 3 = schartype */ + .op = INT, + .letter = L_INT8, + .prop = TDEFINED | TINTEGER | TARITH | TSIGNED, + .size = 1, + .align = 1, + .n.rank = RANK_SCHAR, + }, + { /* 4 = uchartype */ + .op = INT, + .letter = L_UINT8, + .prop = TDEFINED | TINTEGER | TARITH, + .size = 1, + .align = 1, + .n.rank = RANK_UCHAR, + }, + { /* 5 = chartype */ + .op = INT, + .letter = L_INT8, + .prop = TDEFINED | TINTEGER | TARITH | TSIGNED, + .size = 1, + .align = 1, + .n.rank = RANK_CHAR, + }, + { /* 6 = ushortype */ + .op = INT, + .letter = L_UINT16, + .prop = TDEFINED | TINTEGER | TARITH, + .size = 2, + .align = 2, + .n.rank = RANK_USHORT, + }, + { /* 7 = shortype */ + .op = INT, + .letter = L_INT16, + .prop = TDEFINED | TINTEGER | TARITH | TSIGNED, + .size = 2, + .align = 2, + .n.rank = RANK_SHORT, + }, + { /* 8 = uinttype */ + .op = INT, + .letter = L_UINT32, + .prop = TDEFINED | TINTEGER | TARITH, + .size = 4, + .align = 4, + .n.rank = RANK_UINT, + }, + { /* 9 = inttype */ + .op = INT, + .letter = L_INT32, + .prop = TDEFINED | TINTEGER | TARITH | TSIGNED, + .size = 4, + .align = 4, + .n.rank = RANK_INT, + }, + { /* 10 = longtype */ + .op = INT, + .letter = L_INT32, + .prop = TDEFINED | TINTEGER | TARITH | TSIGNED, + .size = 4, + .align = 4, + .n.rank = RANK_LONG, + }, + { /* 11 = ulongtype */ + .op = INT, + .letter = L_UINT32, + .prop = TDEFINED | TINTEGER | TARITH, + .size = 4, + .align = 4, + .n.rank = RANK_ULONG, + }, + { /* 12 = ullongtype */ + .op = INT, + .letter = L_UINT64, + .prop = TDEFINED | TINTEGER | TARITH, + .size = 8, + .align = 4, + .n.rank = RANK_ULLONG, + }, + { /* 13 = llongtype */ + .op = INT, + .letter = L_INT64, + .prop = TDEFINED | TINTEGER | TARITH | TSIGNED, + .size = 8, + .align = 4, + .n.rank = RANK_LLONG, + }, + { /* 14 = floattype */ + .op = FLOAT, + .letter = L_FLOAT, + .prop = TDEFINED | TARITH, + .size = 4, + .align = 4, + .n.rank = RANK_FLOAT, + }, + { /* 15 = doubletype */ + .op = FLOAT, + .letter = L_DOUBLE, + .prop = TDEFINED | TARITH, + .size = 8, + .align = 4, + .n.rank = RANK_DOUBLE, + }, + { /* 16 = ldoubletype */ + .op = FLOAT, + .letter = L_LDOUBLE, + .prop = TDEFINED | TARITH, + .size = 12, + .align = 4, + .n.rank = RANK_LDOUBLE, + }, + { /* 17 = sizettype */ + .op = INT, + .letter = L_UINT32, + .prop = TDEFINED | TINTEGER | TARITH, + .size = 4, + .align = 4, + .n.rank = RANK_UINT, + }, + { /* 18 = ellipsis */ + .op = ELLIPSIS, + .letter = L_ELLIPSIS, + .prop = TDEFINED, + }, + { /* 19 = pdifftype */ + .op = INT, + .letter = L_INT32, + .prop = TDEFINED | TINTEGER | TARITH | TSIGNED, + .size = 4, + .align = 4, + .n.rank = RANK_INT, + }, + { /* 20 = va_list_type */ + .op = PTR, + .letter = L_POINTER, + .prop = TDEFINED, + .size = 4, + .align = 4, + }, +}; + + +Type *voidtype = &types[0], *pvoidtype = &types[1], + *booltype = &types[2], *schartype = &types[3], + *uchartype = &types[4], *chartype = &types[5], + *ushortype = &types[6], *shortype = &types[7], + *uinttype = &types[8], *inttype = &types[9], + *longtype = &types[10], *ulongtype = &types[11], + *ullongtype = &types[12], *llongtype = &types[13], + *floattype = &types[14], *doubletype = &types[15], + *ldoubletype = &types[16], + *sizettype = &types[17], *pdifftype = &types[19], + *ellipsistype = &types[18], *va_list_type = &types[20]; + + + +static Symbol dummy0 = {.u.i = 0, .type = &types[9]}, + dummy1 = {.u.i = 1, .type = &types[9]}; +Symbol *zero = &dummy0, *one = &dummy1; + +void +iarch(void) +{ +} + +int +valid_va_list(Type *tp) +{ + return eqtype(tp, va_list_type, 1); +} diff --git a/src/cc1/target/i386-sysv/arch.mk b/src/cc1/target/i386-sysv/arch.mk @@ -0,0 +1,4 @@ +OBJ-i386-sysv= $(OBJS) target/i386-sysv/arch.o + +$(LIBEXEC)/cc1-i386-sysv: $(OBJ-i386-sysv) + $(CC) $(SCC_LDFLAGS) $(OBJ-i386-sysv) -lscc -o $@ diff --git a/src/cc1/target/z80-scc/arch.c b/src/cc1/target/z80-scc/arch.c @@ -0,0 +1,219 @@ +static char sccsid[] = "@(#) ./cc1/arch/z80/arch.c"; + +#include <scc/scc.h> +#include "../../cc1.h" + +#define RANK_BOOL 0 +#define RANK_SCHAR 1 +#define RANK_UCHAR 1 +#define RANK_CHAR 1 +#define RANK_SHORT 2 +#define RANK_USHORT 2 +#define RANK_INT 3 +#define RANK_UINT 3 +#define RANK_LONG 4 +#define RANK_ULONG 4 +#define RANK_LLONG 5 +#define RANK_ULLONG 5 +#define RANK_FLOAT 6 +#define RANK_DOUBLE 7 +#define RANK_LDOUBLE 8 + +/* + * Initializaion of type pointers were done with + * a C99 initilizator '... = &(Type) {...', but + * c compiler in Plan9 gives error with this + * syntax, so I have switched it to this ugly form + * I hope I will change it again in the future + */ + +static Type types[] = { + { /* 0 = voidtype */ + .op = VOID, + .letter = L_VOID, + }, + { /* 1 = pvoidtype */ + .op = PTR, + .letter = L_POINTER, + .prop = TDEFINED, + .type = &types[5], /* char type */ + .size = 2, + .align = 2, + }, + { /* 2 = booltype */ + .op = INT, + .letter = L_BOOL, + .prop = TDEFINED | TINTEGER | TARITH, + .size = 1, + .align = 1, + .n.rank = RANK_BOOL, + }, + { /* 3 = schartype */ + .op = INT, + .letter = L_INT8, + .prop = TDEFINED | TINTEGER | TARITH | TSIGNED, + .size = 1, + .align = 1, + .n.rank = RANK_SCHAR, + }, + { /* 4 = uchartype */ + .op = INT, + .letter = L_UINT8, + .prop = TDEFINED | TINTEGER | TARITH, + .size = 1, + .align = 1, + .n.rank = RANK_UCHAR, + }, + { /* 5 = chartype */ + .op = INT, + .letter = L_UINT8, + .prop = TDEFINED | TINTEGER | TARITH | TSIGNED, + .size = 1, + .align = 1, + .n.rank = RANK_CHAR, + }, + { /* 6 = ushortype */ + .op = INT, + .letter = L_UINT16, + .prop = TDEFINED | TINTEGER | TARITH, + .size = 2, + .align = 1, + .n.rank = RANK_USHORT, + }, + { /* 7 = shortype */ + .op = INT, + .letter = L_INT16, + .prop = TDEFINED | TINTEGER | TARITH | TSIGNED, + .size = 2, + .align = 1, + .n.rank = RANK_SHORT, + }, + { /* 8 = uinttype */ + .op = INT, + .letter = L_UINT16, + .prop = TDEFINED | TINTEGER | TARITH, + .size = 2, + .align = 1, + .n.rank = RANK_UINT, + }, + { /* 9 = inttype */ + .op = INT, + .letter = L_INT16, + .prop = TDEFINED | TINTEGER | TARITH | TSIGNED, + .size = 2, + .align = 1, + .n.rank = RANK_INT, + }, + { /* 10 = longtype */ + .op = INT, + .letter = L_INT32, + .prop = TDEFINED | TINTEGER | TARITH | TSIGNED, + .size = 4, + .align = 1, + .n.rank = RANK_LONG, + }, + { /* 11 = ulongtype */ + .op = INT, + .letter = L_UINT32, + .prop = TDEFINED | TINTEGER | TARITH, + .size = 4, + .align = 1, + .n.rank = RANK_ULONG, + }, + { /* 12 = ullongtype */ + .op = INT, + .letter = L_UINT64, + .prop = TDEFINED | TINTEGER | TARITH, + .size = 8, + .align = 1, + .n.rank = RANK_ULLONG, + }, + { /* 13 = llongtype */ + .op = INT, + .letter = L_INT64, + .prop = TDEFINED | TINTEGER | TARITH | TSIGNED, + .size = 8, + .align = 1, + .n.rank = RANK_LLONG, + }, + { /* 14 = floattype */ + .op = FLOAT, + .letter = L_FLOAT, + .prop = TDEFINED | TARITH, + .size = 4, + .align = 1, + .n.rank = RANK_FLOAT, + }, + { /* 15 = doubletype */ + .op = FLOAT, + .letter = L_DOUBLE, + .prop = TDEFINED | TARITH, + .size = 8, + .align = 1, + .n.rank = RANK_DOUBLE, + }, + { /* 16 = ldoubletype */ + .op = FLOAT, + .letter = L_LDOUBLE, + .prop = TDEFINED | TARITH, + .size = 16, + .align = 1, + .n.rank = RANK_LDOUBLE, + }, + { /* 17 = sizettype */ + .op = INT, + .letter = L_UINT16, + .prop = TDEFINED | TINTEGER | TARITH, + .size = 2, + .align = 1, + .n.rank = RANK_UINT, + }, + { /* 18 = ellipsis */ + .op = ELLIPSIS, + .letter = L_ELLIPSIS, + .prop = TDEFINED, + }, + { /* 7 = pdifftype */ + .op = INT, + .letter = L_INT16, + .prop = TDEFINED | TINTEGER | TARITH | TSIGNED, + .size = 2, + .align = 1, + .n.rank = RANK_SHORT, + }, + { /* 20 = va_list_type */ + .op = PTR, + .letter = L_POINTER, + .prop = TDEFINED, + .size = 2, + .align = 1, + } +}; + +Type *voidtype = &types[0], *pvoidtype = &types[1], + *booltype = &types[2], *schartype = &types[3], + *uchartype = &types[4], *chartype = &types[5], + *ushortype = &types[6], *shortype = &types[7], + *uinttype = &types[8], *inttype = &types[9], + *longtype = &types[10], *ulongtype = &types[11], + *ullongtype = &types[12], *llongtype = &types[13], + *floattype = &types[14], *doubletype = &types[15], + *ldoubletype = &types[16], + *sizettype = &types[17], *pdifftype = &types[19], + *ellipsistype = &types[18], *va_list_type = &types[20]; + + +static Symbol dummy0 = {.u.i = 0, .type = &types[9]}, + dummy1 = {.u.i = 1, .type = &types[9]}; +Symbol *zero = &dummy0, *one = &dummy1; + +void +iarch(void) +{ +} + +int +valid_va_list(Type *tp) +{ + return eqtype(tp, va_list_type, 1); +} diff --git a/src/cc1/target/z80-scc/arch.mk b/src/cc1/target/z80-scc/arch.mk @@ -0,0 +1,4 @@ +OBJ-z80-scc= $(OBJS) target/z80-scc/arch.o + +$(LIBEXEC)/cc1-z80-scc: $(OBJ-z80-scc) + $(CC) $(SCC_LDFLAGS) $(OBJ-z80-scc) -lscc -o $@ diff --git a/src/cc1/types.c b/src/cc1/types.c @@ -0,0 +1,438 @@ +static char sccsid[] = "@(#) ./cc1/types.c"; +#include <assert.h> +#include <inttypes.h> +#include <stdlib.h> +#include <string.h> + +#include <scc/cstd.h> +#include <scc/scc.h> +#include "cc1.h" + +#define NR_TYPE_HASH 16 +#define HASH(t) (((t)->op ^ (uintptr_t) (t)->type>>3) & NR_TYPE_HASH-1) + +static Type *typetab[NR_TYPE_HASH], *localtypes; + +/* FIXME: + * Compiler can generate warnings here if the ranges of TINT, + * TUINT and TFLOAT are smaller than any of the constants in this + * array. Ignore them if you know that the target types are correct + */ +static struct limits limits[][4] = { + { + { /* 0 = unsigned 1 byte */ + .min.i = 0, + .max.i = 0xff + }, + { /* 1 = unsigned 2 bytes */ + .min.i = 0, + .max.i = 0xffff + }, + { /* 2 = unsigned 4 bytes */ + .min.i = 0, + .max.i = 0xffffffff + }, + { /* 3 = unsigned 8 bytes */ + .min.i = 0, + .max.i = 0xffffffffffffffff + } + }, + { + { /* 0 = signed 1 byte */ + .min.i = -0x7f-1, + .max.i = 0x7f + }, + { /* 1 = signed 2 byte */ + .min.i = -0x7fff-1, + .max.i = 0x7fff + }, + { /* 2 = signed 4 byte */ + .min.i = -0x7fffffff-1, + .max.i = 0x7fffffff + }, + { /* 3 = signed 8 byte */ + .min.i = -0x7fffffffffffffff-1, + .max.i = 0x7fffffffffffffff, + } + }, + { + { + /* 0 = float 4 bytes */ + .min.f = -1, + .max.f = 2 + }, + { + /* 1 = float 8 bytes */ + .min.f = -1, + .max.f = 2, + }, + { + /* 2 = float 16 bytes */ + .min.f = -1, + .max.f = 2, + } + } +}; + +struct limits * +getlimits(Type *tp) +{ + int ntable, ntype; + + switch (tp->op) { + case ENUM: + case INT: + ntable = ((tp->prop & TSIGNED) != 0); + switch (tp->size) { + case 1: ntype = 0; break; + case 2: ntype = 1; break; + case 4: ntype = 2; break; + case 8: ntype = 3; break; + } + break; + case FLOAT: + ntable = 2; + switch (tp->size) { + case 4: ntype = 0; break; + case 8: ntype = 1; break; + case 16: ntype = 2; break; + } + break; + default: + abort(); + } + + return &limits[ntable][ntype]; +} + +Type * +ctype(int type, int sign, int size) +{ + switch (type) { + case CHAR: + if (size) + goto invalid_type; + switch (sign) { + case 0: + return chartype; + case SIGNED: + return schartype; + case UNSIGNED: + return uchartype; + } + break; + case VA_LIST: + if (size || sign) + goto invalid_type; + return va_list_type; + case VOID: + if (size || sign) + goto invalid_type; + return voidtype; + case BOOL: + if (size || sign) + goto invalid_type; + return booltype; + case 0: + case INT: + switch (size) { + case 0: + return (sign == UNSIGNED) ? uinttype : inttype; + case SHORT: + return (sign == UNSIGNED) ? ushortype : shortype; + case LONG: + return (sign == UNSIGNED) ? ulongtype : longtype; + case LLONG: + return (sign == UNSIGNED) ? ullongtype : llongtype; + } + break; + case DOUBLE: + if (size == LLONG) + goto invalid_type; + if (size == LONG) + size = LLONG; + else + size = LONG; + goto floating; + case FLOAT: + if (size == LLONG) + goto invalid_type; + floating: + if (sign) + goto invalid_type; + switch (size) { + case 0: + return floattype; + case LONG: + return doubletype; + case LLONG: + return ldoubletype; + } + break; + } + +invalid_type: + error("invalid type specification"); +} + +void +typesize(Type *tp) +{ + Symbol **sp; + Type *type; + unsigned long size, offset; + int align, a; + TINT n; + + switch (tp->op) { + case ARY: + /* FIXME: Control overflow */ + tp->size = tp->n.elem * tp->type->size; + tp->align = tp->type->align; + return; + case PTR: + tp->size = pvoidtype->size; + tp->align = pvoidtype->align; + return; + case STRUCT: + case UNION: + /* FIXME: Control overflow */ + /* + * The alignment of the struct/union is + * he alignment of the largest included type. + * The size of an union is the size of the largest + * field, and the size of a struct is the sum + * of the size of every field plus padding bits. + */ + offset = align = size = 0; + n = tp->n.elem; + for (sp = tp->p.fields; n--; ++sp) { + (*sp)->u.i = offset; + type = (*sp)->type; + a = type->align; + if (a > align) + align = a; + if (tp->op == STRUCT) { + if (--a != 0) + size = (size + a) & ~a; + size += type->size; + offset = size; + } else { + if (type->size > size) + size = type->size; + } + } + + tp->align = align; + /* + * We have to add the padding bits to + * ensure next struct in an array is well + * alignment. + */ + if (tp->op == STRUCT && align-- > 1) + size += size+align & ~align; + tp->size = size; + return; + case ENUM: + tp->size = inttype->size; + tp->align = inttype->align; + return; + case FTN: + return; + default: + abort(); + } +} + +Type * +deftype(Type *tp) +{ + tp->prop |= TDEFINED; + typesize(tp); + emit(OTYP, tp); + return tp; +} + +static Type * +newtype(Type *base) +{ + Type *tp; + size_t siz; + + tp = xmalloc(sizeof(*tp)); + *tp = *base; + tp->id = newid(); + + if (tp->op == FTN) { + siz = tp->n.elem * sizeof(Type *); + tp->p.pars = memcpy(xmalloc(siz), tp->p.pars, siz); + } + + if (curfun) { + /* it is a type defined in the body of a function */ + tp->next = localtypes; + localtypes = tp; + } + if (tp->prop & TDEFINED) + deftype(tp); + return tp; +} + +Type * +mktype(Type *tp, int op, TINT nelem, Type *pars[]) +{ + Type **tbl, type; + Type *bp; + + if (op == PTR && tp == voidtype) + return pvoidtype; + + memset(&type, 0, sizeof(type)); + type.type = tp; + type.op = op; + type.p.pars = pars; + type.n.elem = nelem; + + switch (op) { + case ARY: + if (tp == voidtype) { + errorp("declaration of array of voids type"); + tp = inttype; + } + type.letter = L_ARRAY; + if (nelem != 0) + type.prop |= TDEFINED; + break; + case KRFTN: + type.prop |= TDEFINED | TK_R; + type.op = FTN; + type.letter = L_FUNCTION; + break; + case FTN: + if (nelem > 0 && pars[nelem-1] == ellipsistype) + type.prop |= TELLIPSIS; + type.letter = L_FUNCTION; + type.prop |= TDEFINED; + break; + case PTR: + type.letter = L_POINTER; + type.prop |= TDEFINED; + break; + case ENUM: + type.letter = inttype->letter; + type.prop |= TINTEGER | TARITH; + type.n.rank = inttype->n.rank; + goto create_type; + case STRUCT: + type.letter = L_STRUCT; + type.prop |= TAGGREG; + goto create_type; + case UNION: + type.letter = L_UNION; + type.prop |= TAGGREG; + create_type: + return newtype(&type); + default: + abort(); + } + + tbl = &typetab[HASH(&type)]; + for (bp = *tbl; bp; bp = bp->h_next) { + if (eqtype(bp, &type, 0)) + return bp; + } + + bp = newtype(&type); + bp->h_next = *tbl; + *tbl = bp; + + return bp; +} + +int +eqtype(Type *tp1, Type *tp2, int equiv) +{ + TINT n; + Type **p1, **p2; + Symbol **s1, **s2; + + if (tp1 == tp2) + return 1; + if (!tp1 || !tp2) + return 0; + if (tp1->op != tp2->op) + return 0; + + switch (tp1->op) { + case UNION: + case STRUCT: + if (tp1->letter != tp2->letter) + return 0; + if (tp1->tag->name || tp2->tag->name) + return tp1->tag == tp2->tag; + if (tp1->n.elem != tp2->n.elem) + return 0; + s1 = tp1->p.fields, s2 = tp2->p.fields; + for (n = tp1->n.elem; n > 0; --n, ++s1, ++s2) { + if (strcmp((*s1)->name, (*s2)->name)) + return 0; + if (!eqtype((*s1)->type, (*s2)->type, equiv)) + return 0; + } + return 1; + case FTN: + if (tp1->n.elem != tp2->n.elem) + return 0; + p1 = tp1->p.pars, p2 = tp2->p.pars; + for (n = tp1->n.elem; n > 0; --n) { + if (!eqtype(*p1++, *p2++, equiv)) + return 0; + } + goto check_base; + case ARY: + if (equiv && (tp1->n.elem == 0 || tp2->n.elem == 0)) + goto check_base; + if (tp1->n.elem != tp2->n.elem) + return 0; + case PTR: + check_base: + return eqtype(tp1->type, tp2->type, equiv); + case VOID: + case ENUM: + return 0; + case INT: + case FLOAT: + return tp1->letter == tp2->letter; + default: + abort(); + } +} + +void +flushtypes(void) +{ + Type *tp, *next, **h; + + for (tp = localtypes; tp; tp = next) { + next = tp->next; + switch (tp->op) { + default: + /* + * All the local types are linked after + * global types, and since we are + * unlinking them in the inverse order + * we do know that tp is always the head + * of the collision list + */ + h = &typetab[HASH(tp)]; + assert(*h == tp); + *h = tp->h_next; + case STRUCT: + case UNION: + case ENUM: + free(tp); + break; + } + } + localtypes = NULL; +} diff --git a/src/cc2/.gitignore b/src/cc2/.gitignore @@ -0,0 +1 @@ +error.h diff --git a/src/cc2/Makefile b/src/cc2/Makefile @@ -0,0 +1,40 @@ +.POSIX: + +PROJECTDIR = ../.. +include $(PROJECTDIR)/scripts/rules.mk + +MORECFLAGS = -I$(INCDIR)/$(STD) + +OBJS = main.o \ + parser.o \ + peep.o \ + symbol.o \ + node.o \ + code.o \ + optm.o \ + +TARGET = $(LIBEXEC)/cc2-amd64-sysv \ + $(LIBEXEC)/cc2-i386-sysv \ + $(LIBEXEC)/cc2-qbe_amd64-sysv \ + $(LIBEXEC)/cc2-z80-scc \ + +all: $(TARGET) + +$(TARGET): error.h + +error.h: cc2.h + rm -f $@;\ + trap 'r=$?;rm -f $$$$.h;exit $r' EXIT INT QUIT ;\ + awk -f generror.awk cc2.h > $$$$.h && mv $$$$.h $@ + +dep: inc-dep + +clean: + rm -f target/*/*.o error.h + +include target/amd64-sysv/target.mk +include target/i386-sysv/target.mk +include target/qbe_amd64-sysv/target.mk +include target/qbe_arm64-sysv/target.mk +include target/z80-scc/target.mk +include deps.mk diff --git a/cc2/cc2.h b/src/cc2/cc2.h diff --git a/src/cc2/code.c b/src/cc2/code.c @@ -0,0 +1,133 @@ +static char sccsid[] = "@(#) ./cc2/code.c"; +#include <stdlib.h> +#include <string.h> + +#include <scc/scc.h> +#include "cc2.h" + +Inst *pc, *prog; + +static void +nextpc(void) +{ + Inst *new; + + new = xcalloc(1, sizeof(*new)); /* TODO: create an arena */ + + if (!pc) { + prog = new; + } else { + new->next = pc->next; + pc->next = new; + } + + /* SNONE being 0, calloc initialized {from1,from2,to}.kind for us */ + new->prev = pc; + pc = new; +} + +static void +addr(Node *np, Addr *addr) +{ + Symbol *sym; + + switch (np->op) { + case OREG: + /* TODO: + * At this moment this op is used also for register variables + */ + addr->kind = SREG; + addr->u.reg = np->u.reg; + break; + case OCONST: + addr->kind = SCONST; + /* TODO: Add support for more type of constants */ + addr->u.i = np->u.i; + break; + case OTMP: + case OLABEL: + case OAUTO: + case OMEM: + sym = np->u.sym; + addr->kind = sym->kind; + addr->u.sym = sym; + break; + default: + abort(); + } +} + +Symbol * +newlabel(void) +{ + Symbol *sym = getsym(TMPSYM); + + sym->kind = SLABEL; + return sym; +} + +Node * +label2node(Node *np, Symbol *sym) +{ + if(!sym) + sym = newlabel(); + if (!np) + np = node(OLABEL); + np->op = OLABEL; + np->u.sym = sym; + + return np; +} + +Node * +constnode(Node *np, TUINT n, Type *tp) +{ + if (!np) + np = node(OCONST); + np->op = OCONST; + np->left = NULL; + np->right = NULL; + np->type = *tp; + np->u.i = n; + return np; +} + +void +setlabel(Symbol *sym) +{ + if (!sym) + return; + code(0, NULL, NULL, NULL); + pc->label = sym; + sym->u.inst = pc; +} + +void +code(int op, Node *to, Node *from1, Node *from2) +{ + nextpc(); + if (from1) + addr(from1, &pc->from1); + if (from2) + addr(from2, &pc->from2); + if (to) + addr(to, &pc->to); + pc->op = op; +} + +void +delcode(void) +{ + Inst *prev = pc->prev, *next = pc->next; + + free(pc); + if (!prev) { + pc = next; + prog = NULL; + } else { + pc = prev; + prev->next = next; + if (next) + next->prev = prev; + } +} diff --git a/src/cc2/deps.mk b/src/cc2/deps.mk @@ -0,0 +1,61 @@ +#deps +code.o: $(INCDIR)/scc/scc/scc.h +code.o: cc2.h +main.o: $(INCDIR)/scc/scc/arg.h +main.o: $(INCDIR)/scc/scc/scc.h +main.o: cc2.h +main.o: error.h +node.o: $(INCDIR)/scc/scc/scc.h +node.o: cc2.h +optm.o: $(INCDIR)/scc/scc/scc.h +optm.o: cc2.h +parser.o: $(INCDIR)/scc/scc/cstd.h +parser.o: $(INCDIR)/scc/scc/scc.h +parser.o: cc2.h +peep.o: $(INCDIR)/scc/scc/scc.h +peep.o: cc2.h +symbol.o: $(INCDIR)/scc/scc/scc.h +symbol.o: cc2.h +target/amd64-sysv/cgen.o: $(INCDIR)/scc/scc/scc.h +target/amd64-sysv/cgen.o: target/amd64-sysv/../../cc2.h +target/amd64-sysv/cgen.o: target/amd64-sysv/arch.h +target/amd64-sysv/code.o: $(INCDIR)/scc/scc/cstd.h +target/amd64-sysv/code.o: $(INCDIR)/scc/scc/scc.h +target/amd64-sysv/code.o: target/amd64-sysv/../../cc2.h +target/amd64-sysv/code.o: target/amd64-sysv/arch.h +target/amd64-sysv/optm.o: $(INCDIR)/scc/scc/scc.h +target/amd64-sysv/optm.o: target/amd64-sysv/../../cc2.h +target/amd64-sysv/types.o: $(INCDIR)/scc/scc/scc.h +target/amd64-sysv/types.o: target/amd64-sysv/../../cc2.h +target/i386-sysv/cgen.o: $(INCDIR)/scc/scc/scc.h +target/i386-sysv/cgen.o: target/i386-sysv/../../cc2.h +target/i386-sysv/cgen.o: target/i386-sysv/arch.h +target/i386-sysv/code.o: $(INCDIR)/scc/scc/cstd.h +target/i386-sysv/code.o: $(INCDIR)/scc/scc/scc.h +target/i386-sysv/code.o: target/i386-sysv/../../cc2.h +target/i386-sysv/code.o: target/i386-sysv/arch.h +target/i386-sysv/optm.o: $(INCDIR)/scc/scc/scc.h +target/i386-sysv/optm.o: target/i386-sysv/../../cc2.h +target/i386-sysv/types.o: $(INCDIR)/scc/scc/scc.h +target/i386-sysv/types.o: target/i386-sysv/../../cc2.h +target/qbe/cgen.o: $(INCDIR)/scc/scc/cstd.h +target/qbe/cgen.o: $(INCDIR)/scc/scc/scc.h +target/qbe/cgen.o: target/qbe/../../cc2.h +target/qbe/cgen.o: target/qbe/arch.h +target/qbe/code.o: $(INCDIR)/scc/scc/cstd.h +target/qbe/code.o: $(INCDIR)/scc/scc/scc.h +target/qbe/code.o: target/qbe/../../cc2.h +target/qbe/code.o: target/qbe/arch.h +target/qbe/optm.o: $(INCDIR)/scc/scc/scc.h +target/qbe/optm.o: target/qbe/../../cc2.h +target/z80-scc/cgen.o: $(INCDIR)/scc/scc/scc.h +target/z80-scc/cgen.o: target/z80-scc/../../cc2.h +target/z80-scc/cgen.o: target/z80-scc/arch.h +target/z80-scc/code.o: $(INCDIR)/scc/scc/cstd.h +target/z80-scc/code.o: $(INCDIR)/scc/scc/scc.h +target/z80-scc/code.o: target/z80-scc/../../cc2.h +target/z80-scc/code.o: target/z80-scc/arch.h +target/z80-scc/optm.o: $(INCDIR)/scc/scc/scc.h +target/z80-scc/optm.o: target/z80-scc/../../cc2.h +target/z80-scc/types.o: $(INCDIR)/scc/scc/scc.h +target/z80-scc/types.o: target/z80-scc/../../cc2.h diff --git a/cc2/generror.awk b/src/cc2/generror.awk diff --git a/src/cc2/main.c b/src/cc2/main.c @@ -0,0 +1,70 @@ +static char sccsid[] = "@(#) ./cc2/main.c"; + +#include <errno.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <scc/arg.h> +#include <scc/scc.h> +#include "cc2.h" +#include "error.h" + +char *argv0; + +void +error(unsigned nerror, ...) +{ + va_list va; + va_start(va, nerror); + vfprintf(stderr, errlist[nerror], va); + va_end(va); + putc('\n', stderr); + exit(1); +} + +static int +moreinput(void) +{ + int c; + +repeat: + if (feof(stdin)) + return 0; + if ((c = getchar()) == '\n' || c == EOF) + goto repeat; + ungetc(c, stdin); + return 1; +} + +static void +usage(void) +{ + fputs("usage: cc2 [irfile]\n", stderr); + exit(1); +} + +int +main(int argc, char *argv[]) +{ + ARGBEGIN { + default: + usage(); + } ARGEND + + if (argv[0] && !freopen(argv[0], "r", stdin)) + die("cc2: %s: %s", argv[0], strerror(errno)); + + while (moreinput()) { + parse(); + apply(optm_ind); + apply(optm_dep); + apply(sethi); + apply(cgen); + getbblocks(); /* TODO: run apply over asm ins too */ + peephole(); + writeout(); + } + return 0; +} diff --git a/src/cc2/node.c b/src/cc2/node.c @@ -0,0 +1,142 @@ +static char sccsid[] = "@(#) ./cc2/node.c"; +#include <stdlib.h> +#include <string.h> + +#include <scc/scc.h> + +#include "cc2.h" + +#define NNODES 32 + +Node *curstmt; +Symbol *curfun; + +static Alloc *arena; + + +Node * +node(int op) +{ + struct arena *ap; + Node *np; + + if (!arena) + arena = alloc(sizeof(Node), NNODES); + np = memset(new(arena), 0, sizeof(*np)); + np->op = op; + + return np; +} + +#ifndef NDEBUG +#include <stdio.h> + +static void +prnode(Node *np) +{ + if (np->left) + prnode(np->left); + if (np->right) + prnode(np->right); + fprintf(stderr, "\t%c%lu", np->op, np->type.size); +} + +void +prtree(Node *np) +{ + prnode(np); + putc('\n', stderr); +} + +void +prforest(char *msg) +{ + Node *np; + + if (!curfun) + return; + + fprintf(stderr, "%s {\n", msg); + for (np = curfun->u.stmt; np; np = np->next) + prtree(np); + fputs("}\n", stderr); +} +#endif + +Node * +addstmt(Node *np, int flag) +{ + if (curstmt) + np->next = curstmt->next; + np->prev = curstmt; + + if (!curfun->u.stmt) + curfun->u.stmt = np; + else + curstmt->next = np; + + if (flag == SETCUR) + curstmt = np; + + return np; +} + +Node * +delstmt(void) +{ + Node *next, *prev; + + next = curstmt->next; + prev = curstmt->prev; + if (next) + next->prev = prev; + if (prev) + prev->next = next; + else + curfun->u.stmt = next; + deltree(curstmt); + + return curstmt = next; +} + +Node * +nextstmt(void) +{ + return curstmt = curstmt->next; +} + +void +delnode(Node *np) +{ + delete(arena, np); +} + +void +deltree(Node *np) +{ + if (!np) + return; + deltree(np->left); + deltree(np->right); + delnode(np); +} + +void +cleannodes(void) +{ + if (arena) { + dealloc(arena); + arena = NULL; + } + curstmt = NULL; +} + +void +apply(Node *(*fun)(Node *)) +{ + if (!curfun) + return; + curstmt = curfun->u.stmt; + while (curstmt) + (*fun)(curstmt) ? nextstmt() : delstmt(); +} diff --git a/src/cc2/optm.c b/src/cc2/optm.c @@ -0,0 +1,9 @@ +#include <scc/scc.h> +#include "cc2.h" + +Node * +optm_ind(Node *np) +{ + return np; +} + diff --git a/src/cc2/parser.c b/src/cc2/parser.c @@ -0,0 +1,722 @@ +static char sccsid[] = "@(#) ./cc2/parser.c"; +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <scc/cstd.h> +#include <scc/scc.h> + +#include "cc2.h" + +#define STACKSIZ 50 + +extern Type int8type, int16type, int32type, int64type, + uint8type, uint16type, uint32type, uint64type, + float32type, float64type, float80type, + booltype, + ptrtype, + voidtype, + arg_type; + +Type funetype = { + .flags = FUNF | ELLIPS +}; + +Type funtype = { + .flags = FUNF +}; + +union tokenop { + void *arg; + unsigned op; +}; + +struct swtch { + int nr; + Node *first; + Node *last; +}; + +static struct swtch swtbl[NR_BLOCK], *swp = swtbl; +static Symbol *lastfun; + +typedef void parsefun(char *, union tokenop); +static parsefun type, symbol, getname, unary, binary, ternary, call, + constant, composed, binit, einit, + jump, oreturn, loop, assign, + ocase, bswitch, eswitch, builtin; + +typedef void evalfun(void); +static evalfun vardecl, beginfun, endfun, endpars, stmt, + array, aggregate, flddecl, labeldcl; + +static struct decoc { + void (*eval)(void); + void (*parse)(char *token, union tokenop); + union tokenop u; +} optbl[] = { /* eval parse args */ + ['A'] = { vardecl, symbol, .u.op = SAUTO<<8 | OAUTO}, + ['R'] = { vardecl, symbol, .u.op = SREG<<8 | OREG}, + ['G'] = { vardecl, symbol, .u.op = SGLOB<<8 | OMEM}, + ['X'] = { vardecl, symbol, .u.op = SEXTRN<<8 | OMEM}, + ['Y'] = { vardecl, symbol, .u.op = SPRIV<<8 | OMEM}, + ['T'] = { vardecl, symbol, .u.op = SLOCAL<<8 | OMEM}, + ['M'] = { flddecl, symbol, .u.op = SMEMB<<8 | OMEM}, + ['L'] = { labeldcl, symbol, .u.op = SLABEL<<8 | OLABEL}, + + ['C'] = { NULL, type, .u.arg = &int8type}, + ['I'] = { NULL, type, .u.arg = &int16type}, + ['W'] = { NULL, type, .u.arg = &int32type}, + ['Q'] = { NULL, type, .u.arg = &int64type}, + ['K'] = { NULL, type, .u.arg = &uint8type}, + ['N'] = { NULL, type, .u.arg = &uint16type}, + ['Z'] = { NULL, type, .u.arg = &uint32type}, + ['O'] = { NULL, type, .u.arg = &uint64type}, + ['J'] = { NULL, type, .u.arg = &float32type}, + ['D'] = { NULL, type, .u.arg = &float64type}, + ['H'] = { NULL, type, .u.arg = &float80type}, + ['0'] = { NULL, type, .u.arg = &voidtype}, + ['B'] = { NULL, type, .u.arg = &booltype}, + ['P'] = { NULL, type, .u.arg = &ptrtype}, + ['E'] = { NULL, type, .u.arg = &funetype}, + ['1'] = { NULL, type, .u.arg = &arg_type}, + + ['F'] = { NULL, type, .u.arg = &funtype}, + ['V'] = { array,composed, 0}, + ['U'] = {aggregate,composed, 0}, + ['S'] = {aggregate,composed, 0}, + + ['"'] = { NULL, getname, 0}, + ['{'] = { beginfun, NULL, 0}, + ['}'] = { endfun, NULL, 0}, + ['('] = { NULL, binit, 0}, + [')'] = { NULL, einit, 0}, + ['\\'] = { endpars, NULL, 0}, + ['\t'] = { stmt, NULL, 0}, + + ['~'] = { NULL, unary, .u.op = OCPL}, + ['_'] = { NULL, unary, .u.op = OSNEG}, + ['\''] = { NULL, unary, .u.op = OADDR}, + ['@'] = { NULL, unary, .u.op = OPTR}, + ['g'] = { NULL, unary, .u.op = OCAST}, + ['p'] = { NULL, unary, .u.op = OPAR}, + ['n'] = { NULL, unary, .u.op = ONEG}, + + ['a'] = { NULL, binary, .u.op = OAND}, + ['o'] = { NULL, binary, .u.op = OOR}, + ['.'] = { NULL, binary, .u.op = OFIELD}, + ['+'] = { NULL, binary, .u.op = OADD}, + ['-'] = { NULL, binary, .u.op = OSUB}, + ['*'] = { NULL, binary, .u.op = OMUL}, + ['%'] = { NULL, binary, .u.op = OMOD}, + ['/'] = { NULL, binary, .u.op = ODIV}, + ['l'] = { NULL, binary, .u.op = OSHL}, + ['r'] = { NULL, binary, .u.op = OSHR}, + ['<'] = { NULL, binary, .u.op = OLT}, + ['>'] = { NULL, binary, .u.op = OGT}, + ['['] = { NULL, binary, .u.op = OLE}, + [']'] = { NULL, binary, .u.op = OGE}, + ['='] = { NULL, binary, .u.op = OEQ}, + ['!'] = { NULL, binary, .u.op = ONE}, + ['&'] = { NULL, binary, .u.op = OBAND}, + ['|'] = { NULL, binary, .u.op = OBOR}, + ['^'] = { NULL, binary, .u.op = OBXOR}, + [','] = { NULL, binary, .u.op = OCOMMA}, + ['m'] = { NULL, builtin,.u.op = OBUILTIN}, + + [':'] = { NULL, assign, .u.op = OASSIG}, + ['?'] = { NULL, ternary, .u.op = OASK}, + ['c'] = { NULL, call, .u.op = OCALL}, + ['z'] = { NULL, call, .u.op = OCALLE}, + + ['#'] = { NULL,constant, .u.op = OCONST}, + + ['j'] = { NULL, jump, .u.op = OJMP}, + ['y'] = { NULL, jump, .u.op = OBRANCH}, + ['h'] = { NULL, oreturn, .u.op = ORET}, + ['i'] = { NULL, NULL, .u.op = OINC}, + ['d'] = { NULL, NULL, .u.op = ODEC}, + + ['b'] = { NULL, loop, .u.op = OBLOOP}, + ['e'] = { NULL, loop, .u.op = OELOOP}, + + ['v'] = { NULL, ocase, .u.op = OCASE}, + ['f'] = { NULL, ocase, .u.op = ODEFAULT}, + ['t'] = { NULL, eswitch, .u.op = OESWITCH}, + ['s'] = { NULL, bswitch, .u.op = OBSWITCH}, +}; + +static int sclass, inpars, ininit, endf, lineno; +static void *stack[STACKSIZ], **sp = stack; + +static Node * +push(void *elem) +{ + if (sp == &stack[STACKSIZ]) + error(ESTACKO); + return *sp++ = elem; +} + +static void * +pop(void) +{ + if (sp == stack) + error(ESTACKU); + return *--sp; +} + +static int +empty(void) +{ + return sp == stack; +} + +static void +type(char *token, union tokenop u) +{ + push(u.arg); +} + +static void +composed(char *token, union tokenop u) +{ + Symbol *sym; + + sym = getsym(atoi(token+1)); + push(&sym->type); +} + +static void +getname(char *t, union tokenop u) +{ + push((*++t) ? xstrdup(t) : NULL); +} + +static void +symbol(char *token, union tokenop u) +{ + Node *np = node(u.op & 0xFF); + Symbol *sym = getsym(atoi(token+1)); + + sclass = u.op >> 8; + np->u.sym = sym; + np->type = sym->type; + push(np); +} + +static Type * +gettype(char *token) +{ + struct decoc *dp; + + dp = &optbl[*token]; + if (!dp->parse) + error(ESYNTAX); + (*dp->parse)(token, dp->u); + return pop(); +} + +static void +constant(char *token, union tokenop u) +{ + static char letters[] = "0123456789ABCDEF"; + Node *np; + TUINT v; + unsigned c; + + ++token; + if (*token == '"') { + ++token; + np = node(OSTRING); + np->type.flags = STRF; + np->type.size = strlen(token); + np->type.align = int8type.align; + np->u.s = xstrdup(token); + } else { + np = node(OCONST); + np->type = *gettype(token++); + for (v = 0; c = *token++; v += c) { + v <<= 4; + c = strchr(letters, c) - letters; + } + np->u.i = v; + } + push(np); +} + +static void +assign(char *token, union tokenop u) +{ + int subop; + Node *np = node(u.op); + + switch (subop = *++token) { + case '+': + case '-': + case '*': + case '%': + case '/': + case 'l': + case 'r': + case '&': + case '|': + case '^': + case 'i': + case 'd': + ++token; + subop = optbl[subop].u.op; + break; + default: + subop = 0; + break; + } + + np->u.subop = subop; + np->type = *gettype(token); + np->right = pop(); + np->left = pop(); + push(np); +} + +static void +ternary(char *token, union tokenop u) +{ + Node *ask = node(OASK), *colon = node(OCOLON); + Type *tp = gettype(token+1); + + colon->right = pop(); + colon->left = pop(); + + ask->type = *tp; + ask->left = pop(); + ask->right = colon; + push(ask); +} + +static void +eval(char *tok) +{ + struct decoc *dp; + + do { + dp = &optbl[*tok]; + if (!dp->parse) + break; + (*dp->parse)(tok, dp->u); + } while (tok = strtok(NULL, "\t\n")); +} + +static int +nextline(void) +{ + static char line[LINESIZ]; + size_t len; + int c; + void (*fun)(void); + +repeat: + ++lineno; + if (!fgets(line, sizeof(line), stdin)) + return 0; + if ((len = strlen(line)) == 0 || line[0] == '\n') + goto repeat; + if (line[len-1] != '\n') + error(len < sizeof(line)-1 ? ELNBLNE : ELNLINE); + line[len-1] = '\0'; + + c = *line; + eval(strtok(line, "\t\n")); + if ((fun = *optbl[c].eval) != NULL) + (*fun)(); + if (sp != stack) + error(ESTACKA); + return 1; +} + +static void +oreturn(char *token, union tokenop u) +{ + Node *np = node(u.op); + + if (token = strtok(NULL, "\t\n")) + eval(token); + if (!empty()) + np->left = pop(); + push(np); +} + +/* + * Move np (which is a OCASE/ODEFAULT/OESWITCH) to be contigous with + * the last switch table. It is a bit ugly to touch directly curstmt + * here, but moving this function to node.c is worse, because we are + * putting knowledge of how the text is parsed into the node + * represtation module. + */ +static void +waft(Node *np) +{ + Node *lastcase, *next;; + struct swtch *cur; + extern Node *curstmt; + + if (swp == swtbl) + error(EWTACKU); + + cur = swp - 1; + lastcase = cur->last; + next = lastcase->next; + + np->next = next; + np->prev = lastcase; + + if (next) + next->prev = np; + lastcase->next = np; + + if (curstmt == cur->last) + curstmt = np; + cur->last = np; + cur->nr++; +} + +static void +bswitch(char *token, union tokenop u) +{ + struct swtch *cur; + Node *np = node(u.op); + + if (swp == &swtbl[NR_BLOCK]) + error(EWTACKO); + cur = swp++; + cur->nr = 0; + + eval(strtok(NULL, "\t\n")); + np->left = pop(); + + push(cur->first = cur->last = np); +} + +static void +eswitch(char *token, union tokenop u) +{ + struct swtch *cur; + + if (swp == swtbl) + error(EWTACKU); + jump(token, u); + waft(pop()); + cur = --swp; + cur->first->u.i = cur->nr; +} + +static void +ocase(char *token, union tokenop u) +{ + jump(token, u); + waft(pop()); +} + +static void +jump(char *token, union tokenop u) +{ + Node *aux, *np = node(u.op); + + eval(strtok(NULL, "\t\n")); + + if (u.op == OBRANCH || u.op == OCASE) + np->left = pop(); + aux = pop(); + np->u.sym = aux->u.sym; + delnode(aux); + push(np); +} + +static void +loop(char *token, union tokenop u) +{ + push(node(u.op)); +} + +static void +unary(char *token, union tokenop u) +{ + Node *np = node(u.op); + + np->type = *gettype(token+1); + np->left = pop(); + np->right = NULL; + push(np); +} + +static void +call(char *token, union tokenop u) +{ + Node *np, *par, *fun = node(u.op); + + for (par = NULL;; par = np) { + np = pop(); + if (np->op != OPAR) + break; + np->right = par; + } + + fun->type = *gettype(token+1); + fun->left = np; + fun->right = par; + push(fun); +} + +static void +builtin(char *token, union tokenop u) +{ + Node *np = node(u.op); + char *name; + unsigned subop, nchilds; + + np->type = *gettype(token+1); + name = pop(); + + if (!strcmp("__builtin_va_arg", name)) { + nchilds = 1; + subop = BVA_ARG; + } else if (!strcmp("__builtin_va_start", name)) { + nchilds = 2; + subop = BVA_START; + } else if (!strcmp("__builtin_va_end", name)) { + nchilds = 1; + subop = BVA_END; + } else if (!strcmp("__builtin_va_copy", name)) { + nchilds = 2; + subop = BVA_COPY; + } else { + error(EBBUILT);; + } + + np->u.subop = subop; + np->right = (nchilds == 2) ? pop() : NULL; + np->left = (nchilds != 0) ? pop() : NULL; + + free(name); + push(np); +} + +static void +binary(char *token, union tokenop u) +{ + Node *np = node(u.op); + + np->type = *gettype(token+1); + np->right = pop(); + np->left = pop(); + push(np); +} + +static void +binit(char *token, union tokenop u) +{ + ininit = 1; +} + +static void +einit(char *token, union tokenop u) +{ + ininit = 0; + endinit(); +} + +static void +endpars(void) +{ + if (!curfun || !inpars) + error(ESYNTAX); + inpars = 0; +} + +static void +aggregate(void) +{ + Node *align, *size; + char *name; + Type *tp; + Symbol *sym; + + align = pop(); + size = pop(); + name = pop(); + tp = pop(); + + tp->size = size->u.i; + tp->align = align->u.i; + tp->flags = AGGRF; + /* + * type is the first field of Symbol so we can obtain the + * address of the symbol from the address of the type. + * We have to do this because composed returns the pointer + * to the type, but in this function we also need the + * symbol to store the name. + */ + sym = (Symbol *) tp; + sym->name = name; + + delnode(align); + delnode(size); +} + +static void +array(void) +{ + Type *tp, *base; + Node *size; + + size = pop(); + base = pop(); + tp = pop(); + tp->size = size->u.i * base->size; /* FIXME check for overflow */ + tp->align = base->align; + + delnode(size); +} + +static void +decl(Symbol *sym) +{ + Type *tp = &sym->type; + + if (tp->flags & FUNF) { + lastfun = sym; + } else { + switch (sym->kind) { + case SEXTRN: + case SGLOB: + case SPRIV: + case SLOCAL: + defglobal(sym); + break; + case SAUTO: + case SREG: + if (!curfun) + error(ESYNTAX); + ((inpars) ? defpar : defvar)(sym); + break; + default: + abort(); + } + } +} + +static void +vardecl(void) +{ + Type *tp, *rp; + Node *np; + Symbol *sym; + char *name; + + name = pop(); + tp = pop(); + if (tp->flags & FUNF) + rp = pop(); + np = pop(); + + sym = np->u.sym; + /* + * We have to free sym->name because in tentative declarations + * we can have multiple declarations of the same symbol, and in + * this case our parser will allocate twice the memory + */ + free(sym->name); + sym->name = name; + sym->type = *tp; + if (tp->flags & FUNF) + sym->rtype = *rp; + sym->kind = sclass; + + if (ininit) + sym->type.flags |= INITF; + decl(sym); + delnode(np); +} + +static void +flddecl(void) +{ + Node *off, *np; + char *name; + Type *tp; + Symbol *sym; + + off = pop(); + name = pop(); + tp = pop(); + np = pop(); + + sym = np->u.sym; + sym->u.off = off->u.i; + sym->name = name; + sym->type = *tp; + + delnode(np); + delnode(off); +} + +static void +labeldcl(void) +{ + Node *np; + Symbol *sym; + + np = pop(); + np->op = ONOP; + sym = np->u.sym; + sym->kind = SLABEL; + sym->u.stmt = np; + np->label = sym; + addstmt(np, SETCUR); +} + +static void +stmt(void) +{ + Node *np; + + if (empty()) + return; + np = pop(); + if (ininit) { + data(np); + deltree(np); + return; + } + addstmt(np, SETCUR); +} + +static void +beginfun(void) +{ + curfun = lastfun; + inpars = 1; + pushctx(); + addstmt(node(OBFUN), SETCUR); +} + +static void +endfun(void) +{ + endf = 1; + addstmt(node(OEFUN), SETCUR); +} + +void +parse(void) +{ + cleannodes(); /* remove code of previous function */ + popctx(); /* remove context of previous function */ + curfun = NULL; + endf = 0; + + while (!endf && nextline()) + ; + if (ferror(stdin)) + error(EFERROR, strerror(errno)); +} diff --git a/src/cc2/peep.c b/src/cc2/peep.c @@ -0,0 +1,8 @@ +static char sccsid[] = "@(#) ./cc2/peep.c"; +#include <scc/scc.h> +#include "cc2.h" + +void +peephole(void) +{ +} diff --git a/src/cc2/symbol.c b/src/cc2/symbol.c @@ -0,0 +1,92 @@ +static char sccsid[] = "@(#) ./cc2/symbol.c"; +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <scc/scc.h> + +#include "cc2.h" + +#define NR_SYMHASH 64 + +Symbol *locals; + +static Symbol *symtab[NR_SYMHASH], *curlocal; +static int infunction; + + +void +freesym(Symbol *sym) +{ + free(sym->name); + free(sym); +} + +void +pushctx(void) +{ + infunction = 1; +} + +void +popctx(void) +{ + Symbol *sym, *next; + + infunction = 0; + for (sym = locals; sym; sym = next) { + next = sym->next; + /* + * Symbols are inserted in the hash in the inverted + * order they are found in locals and it is impossible + * to have a global over a local, because a local is + * any symbol defined in the body of a function, + * even if it has extern linkage. + * For this reason when we reach a symbol in the + * locals list we know that it is the head of it + * collision list and we can remove it assigning + * it h_next to the hash table position + */ + if (sym->id != TMPSYM) + symtab[sym->id & NR_SYMHASH-1] = sym->h_next; + freesym(sym); + } + curlocal = locals = NULL; +} + +Symbol * +getsym(unsigned id) +{ + Symbol **htab, *sym; + static unsigned short num; + + if (id >= USHRT_MAX) + error(EBADID); + + if (id != TMPSYM) { + htab = &symtab[id & NR_SYMHASH-1]; + for (sym = *htab; sym; sym = sym->h_next) { + if (sym->id == id) + return sym; + } + } + + sym = xcalloc(1, sizeof(*sym)); + sym->id = id; + if (infunction) { + if (!locals) + locals = sym; + if (curlocal) + curlocal->next = sym; + curlocal = sym; + } + if (id != TMPSYM) { + sym->h_next = *htab; + *htab = sym; + } + if ((sym->numid = ++num) == 0) + error(EIDOVER); + + return sym; +} diff --git a/cc2/target/amd64-sysv/arch.h b/src/cc2/target/amd64-sysv/arch.h diff --git a/src/cc2/target/amd64-sysv/cgen.c b/src/cc2/target/amd64-sysv/cgen.c @@ -0,0 +1,15 @@ +static char sccsid[] = "@(#) ./cc2/arch/amd64-sysv/cgen.c"; + +#include "arch.h" +#include <scc/scc.h> +#include "../../cc2.h" + +Node * +cgen(Node *np) +{ +} + +Node * +sethi(Node *np) +{ +} diff --git a/src/cc2/target/amd64-sysv/code.c b/src/cc2/target/amd64-sysv/code.c @@ -0,0 +1,211 @@ +static char sccsid[] = "@(#) ./cc2/arch/amd64-sysv/code.c"; + +#include <stdio.h> +#include <stdlib.h> + +#include <scc/cstd.h> +#include <scc/scc.h> + +#include "arch.h" +#include "../../cc2.h" + +enum segment { + CODESEG, + DATASEG, + BSSSEG, + NOSEG +}; + +static int curseg = NOSEG; + +static void +segment(int seg) +{ + static char *txt[] = { + [CODESEG] = "\t.text\n", + [DATASEG] = "\t.data\n", + [BSSSEG] = "\t.bss\n", + }; + + if (seg == curseg) + return; + fputs(txt[seg], stdout); + curseg = seg; +} + +static char * +symname(Symbol *sym) +{ + static char name[INTIDENTSIZ+1]; + + if (sym->name) { + switch (sym->kind) { + case SEXTRN: + case SGLOB: + case SPRIV: + return sym->name; + } + } + + sprintf(name, ".L%d", sym->numid); + + return name; +} + +static void +emitconst(Node *np) +{ + switch (np->type.size) { + case 1: + printf("%d", (int) np->u.i & 0xFF); + break; + case 2: + printf("%d", (int) np->u.i & 0xFFFF); + break; + case 4: + printf("%ld", (long) np->u.i & 0xFFFFFFFF); + break; + case 8: + printf("%lld", (long long) np->u.i & 0xFFFFFFFF); + break; + default: + abort(); + } +} + +static void +emittree(Node *np) +{ + if (!np) + return; + + switch (np->op) { + case OSTRING: + printf("\"%s\"", np->u.s); + free(np->u.s); + np->u.s = NULL; + break; + case OCONST: + emitconst(np); + break; + case OADDR: + emittree(np->left); + break; + case OMEM: + fputs(symname(np->u.sym), stdout); + break; + default: + emittree(np->left); + printf(" %c ", np->op); + emittree(np->right); + break; + } +} +static void +size2asm(Type *tp) +{ + char *s; + + if (tp->flags & STRF) { + s = "\t.ascii\t"; + } else { + switch (tp->size) { + case 1: + s = "\t.byte\t"; + break; + case 2: + s = "\t.short\t"; + break; + case 4: + s = "\t.long\t"; + break; + case 8: + s = "\t.quad\t"; + break; + default: + s = "\t.space\t%lu,"; + break; + } + } + printf(s, tp->size); +} + + +void +data(Node *np) +{ + size2asm(&np->type); + emittree(np); + putchar('\n'); +} + +static void +label(Symbol *sym) +{ + int seg; + char *name = symname(sym); + Type *tp = &sym->type; + + if (sym->type.flags & FUNF) + seg = CODESEG; + else if (sym->type.flags & INITF) + seg = DATASEG; + else + seg = BSSSEG; + segment(seg); + + switch (sym->kind) { + case SEXTRN: + printf("\t.extern\t%s\n", name); + case SLOCAL: + return; + case SGLOB: + printf("\t.global\t%s\n", name); + if (seg == BSSSEG) + printf("\t.comm\t%s,%lu\n", name, tp->size); + break; + } + if (sym->type.align != 1) + printf("\t.align\t%lu\n", sym->type.align ); + printf("%s:\n", name); +} + +void +defglobal(Symbol *sym) +{ + label(sym); + if (sym->kind == SEXTRN || (sym->type.flags & INITF)) + return; + size2asm(&sym->type); + puts("0"); +} + +void +defvar(Symbol *sym) +{ +} + +void +defpar(Symbol *sym) +{ +} + +void +newfun(void) +{ +} + +void +writeout(void) +{ +} + +void +endinit(void) +{ +} + +void +getbblocks(void) +{ +} diff --git a/src/cc2/target/amd64-sysv/optm.c b/src/cc2/target/amd64-sysv/optm.c @@ -0,0 +1,11 @@ +static char sccsid[] = "@(#) ./cc2/arch/amd64-sysv/optm.c"; + +#include <scc/scc.h> + +#include "../../cc2.h" + +Node * +optm_dep(Node *np) +{ + return np; +} diff --git a/src/cc2/target/amd64-sysv/target.mk b/src/cc2/target/amd64-sysv/target.mk @@ -0,0 +1,8 @@ +OBJ-amd64-sysv = $(OBJS) \ + target/amd64-sysv/cgen.o \ + target/amd64-sysv/optm.o \ + target/amd64-sysv/code.o \ + target/amd64-sysv/types.o + +$(LIBEXEC)/cc2-amd64-sysv: $(OBJ-amd64-sysv) + $(CC) $(SCC_LDFLAGS) $(OBJ-amd64-sysv) -lscc -o $@ diff --git a/src/cc2/target/amd64-sysv/types.c b/src/cc2/target/amd64-sysv/types.c @@ -0,0 +1,94 @@ +static char sccsid[] = "@(#) ./cc2/arch/amd64-sysv/types.c"; + +#include <scc/scc.h> + +#include "../../cc2.h" + + +Type int8type = { + .flags = SIGNF | INTF, + .size = 1, + .align = 1 +}; + +Type int16type = { + .flags = SIGNF | INTF, + .size = 2, + .align = 2 +}; + +Type int32type = { + .flags = SIGNF | INTF, + .size = 4, + .align = 4 +}; + +Type int64type = { + .flags = SIGNF | INTF, + .size = 8, + .align = 8 +}; + +Type uint8type = { + .flags = INTF, + .size = 1, + .align = 1 +}; + +Type uint16type = { + .flags = INTF, + .size = 2, + .align = 2 +}; + +Type uint32type = { + .flags = INTF, + .size = 4, + .align = 4 +}; + +Type uint64type = { + .flags = INTF, + .size = 8, + .align = 2 +}; + +Type ptrtype = { + .flags = INTF, + .size = 8, + .align = 8 +}; + +Type booltype = { + .flags = INTF, + .size = 1, + .align = 1 +}; + +Type float32type = { + .flags = FLOATF, + .size = 4, + .align = 4 +}; + +Type float64type = { + .flags = FLOATF, + .size = 8, + .align = 8 +}; + +Type float80type = { + .flags = FLOATF, + .size = 16, + .align = 16 +}; + +Type voidtype = { + .size = 0, + .align = 0 +}; + +Type arg_type = { + .size = 24, + .align = 8 +}; diff --git a/cc2/target/arm64-sysv/types.c b/src/cc2/target/arm64-sysv/types.c diff --git a/cc2/target/i386-sysv/arch.h b/src/cc2/target/i386-sysv/arch.h diff --git a/src/cc2/target/i386-sysv/cgen.c b/src/cc2/target/i386-sysv/cgen.c @@ -0,0 +1,16 @@ +static char sccsid[] = "@(#) ./cc2/arch/i386-sysv/cgen.c"; + +#include <scc/scc.h> + +#include "arch.h" +#include "../../cc2.h" + +Node * +cgen(Node *np) +{ +} + +Node * +sethi(Node *np) +{ +} diff --git a/src/cc2/target/i386-sysv/code.c b/src/cc2/target/i386-sysv/code.c @@ -0,0 +1,209 @@ +static char sccsid[] = "@(#) ./cc2/arch/i386-sysv/code.c"; +#include <stdio.h> +#include <stdlib.h> + +#include <scc/cstd.h> +#include <scc/scc.h> + +#include "arch.h" +#include "../../cc2.h" + +enum segment { + CODESEG, + DATASEG, + BSSSEG, + NOSEG +}; + +static int curseg = NOSEG; + +static void +segment(int seg) +{ + static char *txt[] = { + [CODESEG] = "\t.text\n", + [DATASEG] = "\t.data\n", + [BSSSEG] = "\t.bss\n", + }; + + if (seg == curseg) + return; + fputs(txt[seg], stdout); + curseg = seg; +} + +static char * +symname(Symbol *sym) +{ + static char name[INTIDENTSIZ+1]; + + if (sym->name) { + switch (sym->kind) { + case SEXTRN: + case SGLOB: + case SPRIV: + return sym->name; + } + } + + sprintf(name, ".L%d", sym->numid); + + return name; +} + +static void +emitconst(Node *np) +{ + switch (np->type.size) { + case 1: + printf("%d", (int) np->u.i & 0xFF); + break; + case 2: + printf("%d", (int) np->u.i & 0xFFFF); + break; + case 4: + printf("%ld", (long) np->u.i & 0xFFFFFFFF); + break; + case 8: + printf("%lld", (long long) np->u.i & 0xFFFFFFFF); + break; + default: + abort(); + } +} + +static void +emittree(Node *np) +{ + if (!np) + return; + + switch (np->op) { + case OSTRING: + printf("\"%s\"", np->u.s); + free(np->u.s); + np->u.s = NULL; + break; + case OCONST: + emitconst(np); + break; + case OADDR: + emittree(np->left); + break; + case OMEM: + fputs(symname(np->u.sym), stdout); + break; + default: + emittree(np->left); + printf(" %c ", np->op); + emittree(np->right); + break; + } +} +static void +size2asm(Type *tp) +{ + char *s; + + if (tp->flags & STRF) { + s = "\t.ascii\t"; + } else { + switch (tp->size) { + case 1: + s = "\t.byte\t"; + break; + case 2: + s = "\t.short\t"; + break; + case 4: + s = "\t.long\t"; + break; + case 8: + s = "\t.quad\t"; + break; + default: + s = "\t.space\t%lu,"; + break; + } + } + printf(s, tp->size); +} + +void +data(Node *np) +{ + size2asm(&np->type); + emittree(np); + putchar('\n'); +} + +static void +label(Symbol *sym) +{ + int seg; + char *name = symname(sym); + Type *tp = &sym->type; + + if (sym->type.flags & FUNF) + seg = CODESEG; + else if (sym->type.flags & INITF) + seg = DATASEG; + else + seg = BSSSEG; + segment(seg); + + switch (sym->kind) { + case SEXTRN: + printf("\t.extern\t%s\n", name); + case SLOCAL: + return; + case SGLOB: + printf("\t.global\t%s\n", name); + if (seg == BSSSEG) + printf("\t.comm\t%s,%lu\n", name, tp->size); + break; + } + if (sym->type.align != 1) + printf("\t.align\t%lu\n", sym->type.align ); + printf("%s:\n", name); +} + +void +defglobal(Symbol *sym) +{ + label(sym); + if (sym->kind == SEXTRN || (sym->type.flags & INITF)) + return; + size2asm(&sym->type); + puts("0"); +} + +void +defpar(Symbol *sym) +{ +} + +void +defvar(Symbol *sym) +{ +} + +void +newfun(void) +{ +} + +void +writeout(void) +{ +} + +void +endinit(void) +{ +} + +void +getbblocks(void) +{ +} diff --git a/src/cc2/target/i386-sysv/optm.c b/src/cc2/target/i386-sysv/optm.c @@ -0,0 +1,11 @@ +static char sccsid[] = "@(#) ./cc2/arch/i386-sysv/optm.c"; + +#include <scc/scc.h> + +#include "../../cc2.h" + +Node * +optm_dep(Node *np) +{ + return np; +} diff --git a/src/cc2/target/i386-sysv/target.mk b/src/cc2/target/i386-sysv/target.mk @@ -0,0 +1,8 @@ +OBJ-i386-sysv = $(OBJS) \ + target/i386-sysv/cgen.o \ + target/i386-sysv/optm.o \ + target/i386-sysv/code.o \ + target/i386-sysv/types.o + +$(LIBEXEC)/cc2-i386-sysv: $(OBJ-i386-sysv) + $(CC) $(SCC_LDFLAGS) $(OBJ-i386-sysv) -lscc -o $@ diff --git a/src/cc2/target/i386-sysv/types.c b/src/cc2/target/i386-sysv/types.c @@ -0,0 +1,95 @@ +static char sccsid[] = "@(#) ./cc2/arch/i386-sysv/types.c"; + +#include <scc/scc.h> + +#include "../../cc2.h" + + +Type int8type = { + .flags = SIGNF | INTF, + .size = 1, + .align = 1 +}; + +Type int16type = { + .flags = SIGNF | INTF, + .size = 2, + .align = 2 +}; + +Type int32type = { + .flags = SIGNF | INTF, + .size = 4, + .align = 4 +}; + +Type int64type = { + .flags = SIGNF | INTF, + .size = 8, + .align = 4 +}; + +Type uint8type = { + .flags = INTF, + .size = 1, + .align = 1 +}; + +Type uint16type = { + .flags = INTF, + .size = 2, + .align = 2 +}; + +Type uint32type = { + .flags = INTF, + .size = 4, + .align = 2 +}; + +Type uint64type = { + .flags = INTF, + .size = 8, + .align = 4 +}; + +Type ptrtype = { + .flags = INTF, + .size = 4, + .align = 4 +}; + +Type booltype = { + .flags = INTF, + .size = 1, + .align = 1 +}; + +Type float32type = { + .flags = FLOATF, + .size = 4, + .align = 4 +}; + +Type float64type = { + .flags = FLOATF, + .size = 8, + .align = 4 +}; + +Type float80type = { + .flags = FLOATF, + .size = 12, + .align = 4 +}; + +Type voidtype = { + .size = 0, + .align = 0 +}; + +/* this type is not used in this architecture */ +Type arg_type = { + .size = 0, + .align = 0 +}; diff --git a/cc2/target/qbe/arch.h b/src/cc2/target/qbe/arch.h diff --git a/src/cc2/target/qbe/cgen.c b/src/cc2/target/qbe/cgen.c @@ -0,0 +1,729 @@ +static char sccsid[] = "@(#) ./cc2/arch/qbe/cgen.c"; + +#include <assert.h> +#include <stdlib.h> + +#include <scc/cstd.h> +#include <scc/scc.h> + +#include "arch.h" +#include "../../cc2.h" + +enum sflags { + ISTMP = 1, + ISCONS = 2 +}; + +static char opasmw[] = { + [OADD] = ASADDW, + [OSUB] = ASSUBW, + [OMUL] = ASMULW, + [OMOD] = ASMODW, + [ODIV] = ASDIVW, + [OSHL] = ASSHLW, + [OSHR] = ASSHRW, + [OLT] = ASLTW, + [OGT] = ASGTW, + [OLE] = ASLEW, + [OGE] = ASGEW, + [OEQ] = ASEQW, + [ONE] = ASNEW, + [OBAND] = ASBANDW, + [OBOR] = ASBORW, + [OBXOR] = ASBXORW, +}; + +static char opasml[] = { + [OADD] = ASADDL, + [OSUB] = ASSUBL, + [OMUL] = ASMULL, + [OMOD] = ASMODL, + [ODIV] = ASDIVL, + [OSHL] = ASSHLL, + [OSHR] = ASSHRL, + [OLT] = ASLTL, + [OGT] = ASGTL, + [OLE] = ASLEL, + [OGE] = ASGEL, + [OEQ] = ASEQL, + [ONE] = ASNEL, + [OBAND] = ASBANDL, + [OBOR] = ASBORL, + [OBXOR] = ASBXORL, +}; + +static char opasms[] = { + [OADD] = ASADDS, + [OSUB] = ASSUBS, + [OMUL] = ASMULS, + [ODIV] = ASDIVS, + [OLT] = ASLTS, + [OGT] = ASGTS, + [OLE] = ASLES, + [OGE] = ASGES, + [OEQ] = ASEQS, + [ONE] = ASNES, +}; +static char opasmd[] = { + [OADD] = ASADDD, + [OSUB] = ASSUBD, + [OMUL] = ASMULD, + [ODIV] = ASDIVD, + [OLT] = ASLTD, + [OGT] = ASGTD, + [OLE] = ASLED, + [OGE] = ASGED, + [OEQ] = ASEQD, + [ONE] = ASNED, +}; + +extern Type int32type, uint32type, ptrtype; + +static Node * +tmpnode(Node *np, Type *tp) +{ + char flags; + Symbol *sym; + + if (!np) + np = node(OTMP); + sym = getsym(TMPSYM); + sym->type = np->type = *tp; + flags = tp->flags & ~(PARF|INITF); + sym->type.flags = np->type.flags = flags; + sym->kind = STMP; + np->left = np->right = NULL; + np->u.sym = sym; + np->op = OTMP; + np->flags |= ISTMP; + return np; +} + +static Node * +load(Type *tp, Node *np, Node *new) +{ + int op; + int flags = tp->flags; + + if (flags & (AGGRF|FUNF)) { + *new = *np; + return new; + } + switch (tp->size) { + case 1: + op = ASLDSB; + break; + case 2: + op = ASLDSH; + break; + case 4: + op = (flags & FLOATF) ? ASLDS : ASLDSW; + break; + case 8: + op = (flags & FLOATF) ? ASLDD : ASLDL; + break; + default: + abort(); + } + /* + * unsigned version of operations are always +1 the + * signed version + */ + if ((flags & (INTF|SIGNF)) == INTF && tp->size < 8) + ++op; + + code(op, tmpnode(new, tp), np, NULL); + + return new; +} + +static Node *rhs(Node *np, Node *new); + +static Node * +cast(Type *td, Node *ns, Node *nd) +{ + Type *ts; + Node aux1, aux2; + int op, d_isint, s_isint; + + ts = &ns->type; + d_isint = (td->flags & INTF) != 0; + s_isint = (ts->flags & INTF) != 0; + + if (d_isint && s_isint) { + if (td->size <= ts->size) { + *nd = *ns; + return nd; + } + assert(td->size == 4 || td->size == 8); + switch (ts->size) { + case 1: + op = (td->size == 4) ? ASEXTBW : ASEXTBL; + break; + case 2: + op = (td->size == 4) ? ASEXTHW : ASEXTHL; + break; + case 4: + op = ASEXTWL; + break; + default: + abort(); + } + /* + * unsigned version of operations are always +1 the + * signed version + */ + op += (ts->flags & SIGNF) == 0; + } else if (d_isint) { + /* conversion from float to int */ + switch (ts->size) { + case 4: + op = (td->size == 8) ? ASSTOL : ASSTOW; + break; + case 8: + op = (td->size == 8) ? ASDTOL : ASDTOW; + break; + default: + abort(); + } + /* TODO: Add signess */ + } else if (s_isint) { + /* conversion from int to float */ + switch (ts->size) { + case 1: + case 2: + ts = (ts->flags&SIGNF) ? &int32type : &uint32type; + ns = cast(ts, ns, tmpnode(&aux2, ts)); + case 4: + op = (td->size == 8) ? ASSWTOD : ASSWTOS; + break; + case 8: + op = (td->size == 8) ? ASSLTOD : ASSLTOS; + break; + default: + abort(); + } + /* TODO: Add signess */ + } else { + /* conversion from float to float */ + op = (td->size == 4) ? ASEXTS : ASTRUNCD; + } + + code(op, tmpnode(nd, td), ns, NULL); + return nd; +} + +static Node * +call(Node *np, Node *fun, Node *ret) +{ + int n, op; + Type *tp; + Node aux, **q, *p, *pars[NR_FUNPARAM]; + + for (n = 0, p = np->right; p; p = p->right) + pars[n++] = rhs(p->left, node(OTMP)); + + tp = &np->type; + code(ASCALL, tmpnode(ret, tp), fun, NULL); + + for (q = pars; q < &pars[n]; ++q) { + op = (q == &pars[n-1]) ? ASPARE : ASPAR; + tmpnode(&aux, &(*q)->type); + code(op, NULL, *q, &aux); + } + code((np->op == OCALL) ? ASCALLE : ASCALLEX, NULL, NULL, NULL); + + return ret; +} + +static Node * +assign(Type *tp, Node *to, Node *from) +{ + int op; + + switch (tp->size) { + case 1: + op = ASSTB; + break; + case 2: + op = ASSTH; + break; + case 4: + op = (tp->flags & FLOATF) ? ASSTS : ASSTW; + break; + case 8: + op = (tp->flags & FLOATF) ? ASSTD : ASSTL; + break; + default: + op = ASSTM; + break; + } + code(op, to, from, NULL); + return from; +} + +static Node * +copy(Type *tp, Node *to, Node *from) +{ + int op; + + switch (tp->size) { + case 1: + op = ASCOPYB; + break; + case 2: + op = ASCOPYH; + break; + case 4: + op = (tp->flags & FLOATF) ? ASCOPYS : ASCOPYW; + break; + case 8: + op = (tp->flags & FLOATF) ? ASCOPYD : ASCOPYL; + break; + default: + /* TODO: Need to handle the general case */ + abort(); + } + code(op, to, from, NULL); + return from; +} + +/* TODO: Do field() transformation in sethi */ + +static Node * +field(Node *np, Node *ret, int islhs) +{ + Node base, node, off, add, *addr; + TUINT offset = np->right->u.sym->u.off; + + addr = rhs(np->left, &base); + + if (offset != 0) { + node.op = OADD; + node.type = ptrtype; + node.left = addr; + node.right = constnode(&off, offset, &ptrtype); + addr = rhs(&node, &add); + } + + if (islhs) + *ret = *addr; + else + load(&np->type, addr, ret); + + return ret; +} + +static Node * +lhs(Node *np, Node *new) +{ + switch (np->op) { + case OMEM: + case OAUTO: + *new = *np; + return new; + case OPTR: + return rhs(np->left, new); + case OFIELD: + return field(np, new, 1); + default: + abort(); + } +} + +static void +bool(Node *np, Symbol *true, Symbol *false) +{ + Node *l = np->left, *r = np->right; + Node ret, ifyes, ifno; + Symbol *label; + + switch (np->op) { + case ONEG: + bool(l, false, true); + break; + case OAND: + label = newlabel(); + bool(l, label, false); + setlabel(label); + bool(r, true, false); + break; + case OOR: + label = newlabel(); + bool(l, true, label); + setlabel(label); + bool(r, true, false); + break; + default: + label2node(&ifyes, true); + label2node(&ifno, false); + code(ASBRANCH, rhs(np, &ret), &ifyes, &ifno); + break; + } +} + +static Node * +ternary(Node *np, Node *ret) +{ + Node ifyes, ifno, phi, *colon, aux1, aux2, aux3; + + tmpnode(ret, &np->type); + label2node(&ifyes, NULL); + label2node(&ifno, NULL); + label2node(&phi, NULL); + + colon = np->right; + code(ASBRANCH, rhs(np->left, &aux1), &ifyes, &ifno); + + setlabel(ifyes.u.sym); + copy(&ret->type, ret, rhs(colon->left, &aux2)); + code(ASJMP, NULL, &phi, NULL); + + setlabel(ifno.u.sym); + copy(&ret->type, ret, rhs(colon->right, &aux3)); + setlabel(phi.u.sym); + + return ret; +} + +static Node * +function(void) +{ + Node aux; + Symbol *p; + + /* allocate stack space for parameters */ + for (p = locals; p && (p->type.flags & PARF) != 0; p = p->next) + code(ASALLOC, label2node(&aux, p), NULL, NULL); + + /* allocate stack space for local variables) */ + for ( ; p && p->id != TMPSYM; p = p->next) { + if (p->kind != SAUTO) + continue; + code(ASALLOC, label2node(&aux, p), NULL, NULL); + } + /* store formal parameters in parameters */ + for (p = locals; p; p = p->next) { + if ((p->type.flags & PARF) == 0) + break; + code(ASFORM, label2node(&aux, p), NULL, NULL); + } + return NULL; +} + +static void +swtch_if(Node *idx) +{ + Node aux1, aux2, *np; + Symbol *deflabel = NULL; + + for (;;) { + np = delstmt(); + setlabel(np->label); + + switch (np->op) { + case OESWITCH: + if (!deflabel) + deflabel = np->u.sym; + aux1.op = OJMP; + aux1.label = NULL; + aux1.u.sym = deflabel; + cgen(&aux1); + return; + case OCASE: + aux1 = *np; + aux1.op = OBRANCH; + aux1.label = NULL; + aux1.left = &aux2; + + aux2.op = OEQ; + aux2.type = idx->type; + aux2.left = np->left; + aux2.right = idx; + + cgen(&aux1); + break; + case ODEFAULT: + deflabel = np->u.sym; + break; + default: + abort(); + } + } +} + +static Node * +rhs(Node *np, Node *ret) +{ + Node aux1, aux2, *phi, *l = np->left, *r = np->right; + Type *tp; + int off, op; + char *tbl; + Symbol *true, *false; + + tp = &np->type; + + switch (np->op) { + case OBFUN: + return function(); + case ONOP: + case OBLOOP: + case OELOOP: + case OEFUN: + return NULL; + case OTMP: + case OCONST: + *ret = *np; + return np; + case OMEM: + case OAUTO: + return load(tp, np, ret); + case ONEG: + case OAND: + case OOR: + true = newlabel(); + false = newlabel(); + phi = label2node(&aux1, NULL); + tmpnode(ret, &int32type); + + bool(np, true, false); + + setlabel(true); + code(ASCOPYW, ret, constnode(&aux2, 1, &int32type), NULL); + code(ASJMP, NULL, phi, NULL); + + setlabel(false); + code(ASCOPYW, ret, constnode(&aux2, 0, &int32type), NULL); + + setlabel(phi->u.sym); + return ret; + case OMOD: + case OSHR: + assert(tp->flags & INTF); + case ODIV: + case OLT: + case OGT: + case OLE: + case OGE: + /* + * unsigned version of operations are always +1 the + * signed version + */ + off = (tp->flags & SIGNF) == 0; + goto binary; + case OSHL: + case OBAND: + case OBOR: + case OBXOR: + assert(tp->flags & INTF); + case OADD: + case OSUB: + case OMUL: + case OEQ: + case ONE: + off = 0; + binary: + if (l->complex >= r->complex) { + rhs(l, &aux1); + rhs(r, &aux2); + } else { + rhs(r, &aux2); + rhs(l, &aux1); + } + switch (tp->size) { + case 4: + tbl = (tp->flags & FLOATF) ? opasms : opasmw; + break; + case 8: + tbl = (tp->flags & FLOATF) ? opasmd : opasml; + break; + default: + abort(); + } + op = tbl[np->op] + off; + tmpnode(ret, tp); + code(op, ret, &aux1, &aux2); + return ret; + case OCALL: + case OCALLE: + if (l->op == OPTR) + l = rhs(l, &aux1); + return call(np, l, ret); + case OCAST: + return cast(tp, rhs(l, &aux1), ret); + case OASSIG: + /* TODO: Do this transformations in sethi */ + switch (np->u.subop) { + case OINC: + op = OADD; + goto post_oper; + case ODEC: + op = OSUB; + post_oper: + aux1.op = op; + aux1.left = rhs(l, ret); + aux1.right = r; + aux1.type = np->type; + rhs(&aux1, &aux2); + lhs(l, &aux1); + assign(tp, &aux1, &aux2); + break; + default: + aux2.type = np->type; + aux2.op = np->u.subop; + aux2.right = np->right; + aux2.left = np->left; + r = rhs(&aux2, &aux1); + Node aux3; + if (l->op == OCAST) { + aux3.type = l->left->type; + aux3.op = OCAST; + aux3.left = r; + aux3.right = NULL; + r = &aux3; + l = l->left; + } + case 0: + /* TODO: see what is the most difficult */ + lhs(l, &aux2); + rhs(r, ret); + return assign(tp, &aux2, ret); + } + return ret; + case OASK: + return ternary(np, ret); + case OCOMMA: + rhs(l, &aux1); + return rhs(r, ret); + case OPTR: + return load(tp, rhs(l, &aux1), ret); + case OADDR: + lhs(l, ret); + ret->type = *tp; + return ret; + case OFIELD: + return field(np, ret, 0); + case OBUILTIN: + switch (np->u.subop) { + case BVA_START: + l = rhs(l, &aux1); + code(ASVSTAR, NULL, l, NULL); + return NULL; + case BVA_END: + return NULL; + case BVA_ARG: + l = rhs(l, &aux1); + code(ASVARG, tmpnode(ret, tp), l, NULL); + return ret; + case BVA_COPY: + /* TODO */ + default: + abort(); + } + default: + abort(); + } + abort(); +} + +Node * +cgen(Node *np) +{ + Node aux, *p, *next; + + setlabel(np->label); + switch (np->op) { + case OJMP: + label2node(&aux, np->u.sym); + code(ASJMP, NULL, &aux, NULL); + break; + case OBRANCH: + next = np->next; + if (!next->label) + next->label = newlabel(); + bool(np->left, np->u.sym, next->label); + break; + case ORET: + p = (np->left) ? rhs(np->left, &aux) : NULL; + code(ASRET, NULL, p, NULL); + break; + case OBSWITCH: + p = rhs(np->left, &aux); + swtch_if(p); + break; + default: + rhs(np, &aux); + break; + } + return NULL; +} + +/* + * This is strongly influenced by + * http://plan9.bell-labs.com/sys/doc/compiler.ps (/sys/doc/compiler.ps) + * calculate addresability as follows + * AUTO => 11 value+fp + * REG => 11 reg + * STATIC => 11 (value) + * CONST => 11 $value + * These values of addressability are not used in the code generation. + * They are only used to calculate the Sethi-Ullman numbers. Since + * QBE is AMD64 targered we could do a better job there, and try to + * detect some of the complex addressing modes of these processors. + */ +Node * +sethi(Node *np) +{ + Node *lp, *rp; + + if (!np) + return np; + + np->complex = 0; + np->address = 0; + lp = np->left; + rp = np->right; + + switch (np->op) { + case OAUTO: + case OREG: + case OMEM: + case OCONST: + np->address = 11; + break; + case OCPL: + assert(np->type.flags & INTF); + np->op = OBXOR; + rp = constnode(NULL, ~(TUINT) 0, &np->type); + goto binary; + case OSNEG: + np->op = OSUB; + rp = lp; + lp = constnode(NULL, 0, &np->type); + if ((np->type.flags & INTF) == 0) + lp->u.f = 0.0; + default: + binary: + lp = sethi(lp); + rp = sethi(rp); + break; + } + np->left = lp; + np->right = rp; + + if (np->address > 10) + return np; + if (lp) + np->complex = lp->complex; + if (rp) { + int d = np->complex - rp->complex; + + if (d == 0) + ++np->complex; + else if (d < 0) + np->complex = rp->complex; + } + if (np->complex == 0) + ++np->complex; + return np; +} diff --git a/src/cc2/target/qbe/code.c b/src/cc2/target/qbe/code.c @@ -0,0 +1,569 @@ +static char sccsid[] = "@(#) ./cc2/arch/qbe/code.c"; + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <scc/cstd.h> +#include <scc/scc.h> + +#include "arch.h" +#include "../../cc2.h" + +#define ADDR_LEN (INTIDENTSIZ+64) + +static void binary(void), unary(void), store(void), jmp(void), ret(void), + branch(void), call(void), ecall(void), param(void), + asalloc(void), form2local(void), ldir(void), vastart(void), + vaarg(void); + +static struct opdata { + void (*fun)(void); + char *txt; + char letter; +} optbl [] = { + [ASLDSB] = {.fun = unary, .txt = "loadsb", .letter = 'w'}, + [ASLDUB] = {.fun = unary, .txt = "loadub", .letter = 'w'}, + [ASLDSH] = {.fun = unary, .txt = "loadsh", .letter = 'w'}, + [ASLDUH] = {.fun = unary, .txt = "loaduh", .letter = 'w'}, + [ASLDSW] = {.fun = unary, .txt = "loadsw", .letter = 'w'}, + [ASLDUW] = {.fun = unary, .txt = "loaduw", .letter = 'w'}, + [ASLDL] = {.fun = unary, .txt = "loadl", .letter = 'l'}, + [ASLDS] = {.fun = unary, .txt = "loads", .letter = 's'}, + [ASLDD] = {.fun = unary, .txt = "loadd", .letter = 'd'}, + + [ASCOPYB] = {.fun = unary, .txt = "copy", .letter = 'b'}, + [ASCOPYH] = {.fun = unary, .txt = "copy", .letter = 'h'}, + [ASCOPYW] = {.fun = unary, .txt = "copy", .letter = 'w'}, + [ASCOPYL] = {.fun = unary, .txt = "copy", .letter = 'l'}, + [ASCOPYS] = {.fun = unary, .txt = "copy", .letter = 's'}, + [ASCOPYD] = {.fun = unary, .txt = "copy", .letter = 'd'}, + + [ASSTB] = {.fun = store, .txt = "store", .letter = 'b'}, + [ASSTH] = {.fun = store, .txt = "store", .letter = 'h'}, + [ASSTW] = {.fun = store, .txt = "store", .letter = 'w'}, + [ASSTL] = {.fun = store, .txt = "store", .letter = 'l'}, + [ASSTM] = {.fun = ldir}, + [ASSTS] = {.fun = store, .txt = "store", .letter = 's'}, + [ASSTD] = {.fun = store, .txt = "store", .letter = 'd'}, + + [ASADDW] = {.fun = binary, .txt = "add", .letter = 'w'}, + [ASSUBW] = {.fun = binary, .txt = "sub", .letter = 'w'}, + [ASMULW] = {.fun = binary, .txt = "mul", .letter = 'w'}, + [ASMODW] = {.fun = binary, .txt = "rem", .letter = 'w'}, + [ASUMODW] = {.fun = binary, .txt = "urem", .letter = 'w'}, + [ASDIVW] = {.fun = binary, .txt = "div", .letter = 'w'}, + [ASUDIVW] = {.fun = binary, .txt = "udiv", .letter = 'w'}, + [ASSHLW] = {.fun = binary, .txt = "shl", .letter = 'w'}, + [ASSHRW] = {.fun = binary, .txt = "sar", .letter = 'w'}, + [ASUSHRW] = {.fun = binary, .txt = "shr", .letter = 'w'}, + [ASLTW] = {.fun = binary, .txt = "csltw", .letter = 'w'}, + [ASULTW] = {.fun = binary, .txt = "cultw", .letter = 'w'}, + [ASGTW] = {.fun = binary, .txt = "csgtw", .letter = 'w'}, + [ASUGTW] = {.fun = binary, .txt = "cugtw", .letter = 'w'}, + [ASLEW] = {.fun = binary, .txt = "cslew", .letter = 'w'}, + [ASULEW] = {.fun = binary, .txt = "culew", .letter = 'w'}, + [ASGEW] = {.fun = binary, .txt = "csgew", .letter = 'w'}, + [ASUGEW] = {.fun = binary, .txt = "cugew", .letter = 'w'}, + [ASEQW] = {.fun = binary, .txt = "ceqw", .letter = 'w'}, + [ASNEW] = {.fun = binary, .txt = "cnew", .letter = 'w'}, + [ASBANDW] = {.fun = binary, .txt = "and", .letter = 'w'}, + [ASBORW] = {.fun = binary, .txt = "or", .letter = 'w'}, + [ASBXORW] = {.fun = binary, .txt = "xor", .letter = 'w'}, + + [ASADDL] = {.fun = binary, .txt = "add", .letter = 'l'}, + [ASSUBL] = {.fun = binary, .txt = "sub", .letter = 'l'}, + [ASMULL] = {.fun = binary, .txt = "mul", .letter = 'l'}, + [ASMODL] = {.fun = binary, .txt = "rem", .letter = 'l'}, + [ASUMODL] = {.fun = binary, .txt = "urem", .letter = 'l'}, + [ASDIVL] = {.fun = binary, .txt = "div", .letter = 'l'}, + [ASUDIVL] = {.fun = binary, .txt = "udiv", .letter = 'l'}, + [ASSHLL] = {.fun = binary, .txt = "shl", .letter = 'l'}, + [ASSHRL] = {.fun = binary, .txt = "sar", .letter = 'l'}, + [ASUSHRL] = {.fun = binary, .txt = "shr", .letter = 'l'}, + [ASLTL] = {.fun = binary, .txt = "csltl", .letter = 'w'}, + [ASULTL] = {.fun = binary, .txt = "cultl", .letter = 'w'}, + [ASGTL] = {.fun = binary, .txt = "csgtl", .letter = 'w'}, + [ASUGTL] = {.fun = binary, .txt = "cugtl", .letter = 'w'}, + [ASLEL] = {.fun = binary, .txt = "cslel", .letter = 'w'}, + [ASULEL] = {.fun = binary, .txt = "culel", .letter = 'w'}, + [ASGEL] = {.fun = binary, .txt = "csgel", .letter = 'w'}, + [ASUGEL] = {.fun = binary, .txt = "cugel", .letter = 'w'}, + [ASEQL] = {.fun = binary, .txt = "ceql", .letter = 'w'}, + [ASNEL] = {.fun = binary, .txt = "cnel", .letter = 'w'}, + [ASBANDL] = {.fun = binary, .txt = "and", .letter = 'l'}, + [ASBORL] = {.fun = binary, .txt = "or", .letter = 'l'}, + [ASBXORL] = {.fun = binary, .txt = "xor", .letter = 'l'}, + + [ASADDS] = {.fun = binary, .txt = "add", .letter = 's'}, + [ASSUBS] = {.fun = binary, .txt = "sub", .letter = 's'}, + [ASMULS] = {.fun = binary, .txt = "mul", .letter = 's'}, + [ASDIVS] = {.fun = binary, .txt = "div", .letter = 's'}, + [ASLTS] = {.fun = binary, .txt = "clts", .letter = 'w'}, + [ASGTS] = {.fun = binary, .txt = "cgts", .letter = 'w'}, + [ASLES] = {.fun = binary, .txt = "cles", .letter = 'w'}, + [ASGES] = {.fun = binary, .txt = "cges", .letter = 'w'}, + [ASEQS] = {.fun = binary, .txt = "ceqs", .letter = 'w'}, + [ASNES] = {.fun = binary, .txt = "cnes", .letter = 'w'}, + + [ASADDD] = {.fun = binary, .txt = "add", .letter = 'd'}, + [ASSUBD] = {.fun = binary, .txt = "sub", .letter = 'd'}, + [ASMULD] = {.fun = binary, .txt = "mul", .letter = 'd'}, + [ASDIVD] = {.fun = binary, .txt = "div", .letter = 'd'}, + [ASLTD] = {.fun = binary, .txt = "cltd", .letter = 'w'}, + [ASGTD] = {.fun = binary, .txt = "cgtd", .letter = 'w'}, + [ASLED] = {.fun = binary, .txt = "cled", .letter = 'w'}, + [ASGED] = {.fun = binary, .txt = "cged", .letter = 'w'}, + [ASEQD] = {.fun = binary, .txt = "ceqd", .letter = 'w'}, + [ASNED] = {.fun = binary, .txt = "cned", .letter = 'w'}, + + [ASEXTBW] = {.fun = unary, .txt = "extsb", .letter = 'w'}, + [ASUEXTBW]= {.fun = unary, .txt = "extub", .letter = 'w'}, + [ASEXTBL] = {.fun = unary, .txt = "extsb", .letter = 'l'}, + [ASUEXTBL]= {.fun = unary, .txt = "extub", .letter = 'l'}, + [ASEXTHW] = {.fun = unary, .txt = "extsh", .letter = 'w'}, + [ASUEXTHW]= {.fun = unary, .txt = "extuh", .letter = 'w'}, + [ASEXTWL] = {.fun = unary, .txt = "extsw", .letter = 'l'}, + [ASUEXTWL]= {.fun = unary, .txt = "extuw", .letter = 'l'}, + + [ASSTOL] = {.fun = unary, .txt = "stosi", .letter = 'l'}, + [ASSTOW] = {.fun = unary, .txt = "stosi", .letter = 'w'}, + [ASDTOL] = {.fun = unary, .txt = "dtosi", .letter = 'l'}, + [ASDTOW] = {.fun = unary, .txt = "dtosi", .letter = 'w'}, + + [ASSWTOD] = {.fun = unary, .txt = "swtof", .letter = 'd'}, + [ASSWTOS] = {.fun = unary, .txt = "swtof", .letter = 's'}, + [ASSLTOD] = {.fun = unary, .txt = "sltof", .letter = 'd'}, + [ASSLTOS] = {.fun = unary, .txt = "sltof", .letter = 's'}, + + [ASEXTS] = {.fun = unary, .txt = "exts", .letter = 'd'}, + [ASTRUNCD] = {.fun = unary, .txt = "truncd", .letter = 's'}, + + [ASBRANCH] = {.fun = branch}, + [ASJMP] = {.fun = jmp}, + [ASRET] = {.fun = ret}, + [ASCALL] = {.fun = call}, + [ASCALLE] = {.fun = ecall, .txt = ")"}, + [ASCALLEX] = {.fun = ecall, .txt = ", ...)"}, + [ASPAR] = {.fun = param, .txt = "%s %s, "}, + [ASPARE] = {.fun = param, .txt = "%s %s"}, + [ASALLOC] = {.fun = asalloc}, + [ASFORM] = {.fun = form2local}, + + [ASVSTAR] = {.fun = vastart}, + [ASVARG] = {.fun = vaarg}, +}; + +static char buff[ADDR_LEN]; +/* + * : is for user-defined Aggregate Types + * $ is for globals (represented by a pointer) + * % is for function-scope temporaries + * @ is for block labels + */ +static char +sigil(Symbol *sym) +{ + switch (sym->kind) { + case SEXTRN: + case SGLOB: + case SPRIV: + case SLOCAL: + return '$'; + case SAUTO: + case STMP: + return '%'; + case SLABEL: + return '@'; + default: + abort(); + } +} + +static char * +symname(Symbol *sym) +{ + char c = sigil(sym); + + if (sym->name) { + switch (sym->kind) { + case SEXTRN: + case SGLOB: + sprintf(buff, "%c%s", c, sym->name); + return buff; + case SLOCAL: + case SPRIV: + case SAUTO: + sprintf(buff, "%c%s.%u", c, sym->name, sym->id); + return buff; + default: + abort(); + } + } + sprintf(buff, "%c.%u", c, sym->numid); + + return buff; +} + +static void +emitconst(Node *np) +{ + switch (np->type.size) { + case 1: + printf("%d", (int) np->u.i & 0xFF); + break; + case 2: + printf("%d", (int) np->u.i & 0xFFFF); + break; + case 4: + printf("%ld", (long) np->u.i & 0xFFFFFFFF); + break; + case 8: + printf("%lld", (long long) np->u.i); + break; + default: + abort(); + } +} + +static void +emittree(Node *np) +{ + if (!np) + return; + + switch (np->op) { + case OSTRING: + printf("\"%s\"", np->u.s); + free(np->u.s); + np->u.s = NULL; + break; + case OCONST: + emitconst(np); + break; + case OADDR: + emittree(np->left); + break; + case OMEM: + fputs(symname(np->u.sym), stdout); + break; + default: + emittree(np->left); + printf(" %c ", np->op); + emittree(np->right); + break; + } +} + +static char * +size2asm(Type *tp) +{ + if (tp->flags & STRF) { + return "b"; + } else if (tp->flags & INTF) { + switch (tp->size) { + case 1: + return "b"; + case 2: + return "h"; + case 4: + return "w"; + case 8: + return "l"; + } + } else if (tp->flags & FLOATF) { + if (tp->size == 4) + return "s"; + else if (tp->size == 8) + return "d"; + } + abort(); +} + +void +defglobal(Symbol *sym) +{ + if (sym->kind == SEXTRN) + return; + if (sym->kind == SGLOB) + fputs("export ", stdout); + printf("data %s = {\n", symname(sym)); + if (sym->type.flags & INITF) + return; + printf("\tz\t%lu\n}\n", sym->type.size); +} + +void +defpar(Symbol *sym) +{ + sym->type.flags |= PARF; +} + +void +defvar(Symbol *sym) +{ + if (sym->kind == SREG) + sym->kind = SAUTO; +} + +void +data(Node *np) +{ + printf("\t%s\t", size2asm(&np->type)); + emittree(np); + putchar(','); + putchar('\n'); +} + +static char * +size2stack(Type *tp) +{ + if (tp->flags & INTF) { + switch (tp->size) { + case 1: + case 2: + case 4: + return "w"; + case 8: + return "l"; + } + } else if (tp->flags & FLOATF) { + if (tp->size == 4) + return "s"; + else if (tp->size == 8) + return "d"; + } else if (tp->size == 0) { + return "w"; + } + abort(); +} + +void +writeout(void) +{ + Symbol *p; + Type *tp; + char *sep, *name; + int haslabel = 0; + + if (!curfun) + return; + if (curfun->kind == SGLOB) + fputs("export ", stdout); + printf("function %s %s(", size2stack(&curfun->rtype), symname(curfun)); + + /* declare formal parameters */ + for (sep = "", p = locals; p; p = p->next, sep = ",") { + if ((p->type.flags & PARF) == 0) + break; + printf("%s%s %s.val", sep, size2stack(&p->type), symname(p)); + } + printf("%s)\n{\n", (curfun->type.flags&ELLIPS) ? ", ..." : ""); + + /* emit assembler instructions */ + for (pc = prog; pc; pc = pc->next) { + if (pc->label) { + haslabel = 1; + printf("%s\n", symname(pc->label)); + } + if (!pc->op) + continue; + if (pc->flags&BBENTRY && !haslabel) + printf("%s\n", symname(newlabel())); + (*optbl[pc->op].fun)(); + if (!pc->label) + haslabel = 0; + } + + puts("}"); +} + +static char * +addr2txt(Addr *a) +{ + switch (a->kind) { + case SCONST: + sprintf(buff, "%llu", (unsigned long long) a->u.i); + return buff; + case SAUTO: + case SLABEL: + case STMP: + case SGLOB: + case SEXTRN: + case SPRIV: + case SLOCAL: + return symname(a->u.sym); + default: + abort(); + } +} + +static void +binary(void) +{ + struct opdata *p = &optbl[pc->op]; + char to[ADDR_LEN], from1[ADDR_LEN], from2[ADDR_LEN]; + + strcpy(to, addr2txt(&pc->to)); + strcpy(from1, addr2txt(&pc->from1)); + strcpy(from2, addr2txt(&pc->from2)); + printf("\t%s =%c\t%s\t%s,%s\n", to, p->letter, p->txt, from1, from2); +} + +static void +ldir(void) +{ + struct opdata *p = &optbl[pc->op]; + char to[ADDR_LEN], from[ADDR_LEN]; + /* TODO: what type do we use for the size? */ + + /* TODO: it is pending */ +} + +static void +store(void) +{ + struct opdata *p = &optbl[pc->op]; + char to[ADDR_LEN], from[ADDR_LEN]; + + strcpy(to, addr2txt(&pc->to)); + strcpy(from, addr2txt(&pc->from1)); + printf("\t\t%s%c\t%s,%s\n", p->txt, p->letter, from, to); +} + +static void +unary(void) +{ + struct opdata *p = &optbl[pc->op]; + char to[ADDR_LEN], from[ADDR_LEN]; + + strcpy(to, addr2txt(&pc->to)); + strcpy(from, addr2txt(&pc->from1)); + printf("\t%s =%c\t%s\t%s\n", to, p->letter, p->txt, from); +} + +static void +call(void) +{ + struct opdata *p = &optbl[pc->op]; + char to[ADDR_LEN], from[ADDR_LEN]; + Symbol *sym = pc->to.u.sym; + + strcpy(to, addr2txt(&pc->to)); + strcpy(from, addr2txt(&pc->from1)); + printf("\t%s =%s\tcall\t%s(", + to, size2stack(&sym->type), from); +} + +static void +param(void) +{ + Symbol *sym = pc->from2.u.sym; + + printf(optbl[pc->op].txt, + size2stack(&sym->type), addr2txt(&pc->from1)); +} + +static void +ecall(void) +{ + struct opdata *p = &optbl[pc->op]; + + puts(p->txt); +} + +static void +ret(void) +{ + if (pc->from1.kind == SNONE) + puts("\t\tret"); + else + printf("\t\tret\t%s\n", addr2txt(&pc->from1)); +} + +static void +jmp(void) +{ + printf("\t\tjmp\t%s\n", addr2txt(&pc->from1)); +} + +static void +branch(void) +{ + char to[ADDR_LEN], from1[ADDR_LEN], from2[ADDR_LEN]; + + strcpy(to, addr2txt(&pc->to)); + strcpy(from1, addr2txt(&pc->from1)); + strcpy(from2, addr2txt(&pc->from2)); + printf("\t\tjnz\t%s,%s,%s\n", to, from1, from2); +} + +static void +vastart(void) +{ + printf("\t\tvastart %s\n", addr2txt(&pc->from1)); +} + +static void +vaarg(void) +{ + Symbol *sym = pc->to.u.sym; + Type *tp = &sym->type; + char to[ADDR_LEN], from[ADDR_LEN]; + + strcpy(to, addr2txt(&pc->to)); + strcpy(from, addr2txt(&pc->from1)); + printf("\t\t%s =%s vaarg %s\n", to, size2asm(tp), from); +} + +static void +asalloc(void) +{ + Symbol *sym = pc->to.u.sym; + Type *tp = &sym->type; + extern Type ptrtype; + + printf("\t%s =%s\talloc%lu\t%lu\n", + symname(sym), size2asm(&ptrtype), tp->align+3 & ~3, tp->size); +} + +static void +form2local(void) +{ + Symbol *sym = pc->to.u.sym; + Type *tp = &sym->type; + char *name = symname(sym); + + printf("\t\tstore%s\t%s.val,%s\n", size2asm(tp), name, name); +} + +void +endinit(void) +{ + puts("}"); +} + +void +getbblocks(void) +{ + Inst *i; + + if (!prog) + return; + + prog->flags |= BBENTRY; + for (pc = prog; pc; pc = pc->next) { + switch (pc->op) { + case ASBRANCH: + i = pc->from2.u.sym->u.inst; + i->flags |= BBENTRY; + case ASJMP: + i = pc->from1.u.sym->u.inst; + i->flags |= BBENTRY; + case ASRET: + if (pc->next) + pc->next->flags |= BBENTRY; + break; + } + } +} diff --git a/src/cc2/target/qbe/optm.c b/src/cc2/target/qbe/optm.c @@ -0,0 +1,58 @@ +static char sccsid[] = "@(#) ./cc2/arch/qbe/optm.c"; + +#include <stddef.h> + +#include <scc/scc.h> + +#include "../../cc2.h" + +Node * +optm_dep(Node *np) +{ + int op = np->op; + Node *p, *dst, *next = np->next; + Symbol *sym, *osym; + + switch (op) { + case OEFUN: + /* + * In QBE we need at the end of a basic block + * a jump, so we have to ensure that the last + * statement of the function is a ret, a jmp + * or a branch. In the same way, QBE does + * not accept labels at the end of a function + * (ONOP is used for labels) so we have to add + * a ret there, and in the case of branches + * we need a label for the next statement + */ + op = (np->prev) ? np->prev->op : 0; + if (!op || op == ONOP || op == OBRANCH || (op != ORET && op != OJMP)) + addstmt(node(ORET), KEEPCUR); + break; + case OBRANCH: + if (!next->label) { + sym = getsym(TMPSYM); + sym->kind = SLABEL; + next->label = sym; + } + case OJMP: + for (;;) { + dst = np->u.sym->u.stmt; + if (dst->op != OJMP) + break; + np->u.sym = dst->u.sym; + } + for (p = np->next; p; p = p->next) { + if (p == dst) + return NULL; + if (p->op == ONOP || + p->op == OBLOOP || + p->op == OELOOP) { + continue; + } + break; + } + break; + } + return np; +} diff --git a/src/cc2/target/qbe_amd64-sysv/target.mk b/src/cc2/target/qbe_amd64-sysv/target.mk @@ -0,0 +1,8 @@ +OBJ-qbe_amd64-sysv = $(OBJS) \ + target/qbe/cgen.o \ + target/qbe/optm.o \ + target/qbe/code.o \ + target/amd64-sysv/types.o + +$(LIBEXEC)/cc2-qbe_amd64-sysv: $(OBJ-qbe_amd64-sysv) + $(CC) $(SCC_LDFLAGS) $(OBJ-qbe_amd64-sysv) -lscc -o $@ diff --git a/src/cc2/target/qbe_arm64-sysv/target.mk b/src/cc2/target/qbe_arm64-sysv/target.mk @@ -0,0 +1,5 @@ +OBJ-qbe_arm64-sysv = $(OBJS) \ + target/qbe/cgen.o \ + target/qbe/optm.o \ + target/qbe/code.o \ + target/arm64-sysv/types.o \ diff --git a/cc2/target/z80-scc/arch.h b/src/cc2/target/z80-scc/arch.h diff --git a/src/cc2/target/z80-scc/cgen.c b/src/cc2/target/z80-scc/cgen.c @@ -0,0 +1,161 @@ +static char sccsid[] = "@(#) ./cc2/arch/z80/cgen.c"; + +#include <stdlib.h> + +#include <scc/scc.h> + +#include "arch.h" +#include "../../cc2.h" + +static void +swtch(Node *idx) +{ +} + +static Node * +rhs(Node *np, Node *ret) +{ +} + +static Node * +field(Node *np, Node *ret, int islhs) +{ +} + +static Node * +lhs(Node *np, Node *new) +{ + switch (np->op) { + case OMEM: + case OAUTO: + *new = *np; + return new; + case OPTR: + return rhs(np->left, new); + case OFIELD: + return field(np, new, 1); + default: + abort(); + } +} + +static void +bool(Node *np, Symbol *true, Symbol *false) +{ + Node *l = np->left, *r = np->right; + Node ret, ifyes, ifno; + Symbol *label; + + switch (np->op) { + case ONEG: + bool(l, false, true); + break; + case OAND: + label = newlabel(); + bool(l, label, false); + setlabel(label); + bool(r, true, false); + break; + case OOR: + label = newlabel(); + bool(l, true, label); + setlabel(label); + bool(r, true, false); + break; + default: + label2node(&ifyes, true); + label2node(&ifno, false); + code(ASBRANCH, rhs(np, &ret), &ifyes, &ifno); + break; + } +} + +Node * +cgen(Node *np) +{ + Node aux, *p, *next; + + setlabel(np->label); + switch (np->op) { + case OJMP: + label2node(&aux, np->u.sym); + code(ASJMP, NULL, &aux, NULL); + break; + case OBRANCH: + next = np->next; + if (!next->label) + next->label = newlabel(); + bool(np->left, np->u.sym, next->label); + break; + case ORET: + p = np->left; + if (p) + p = rhs(np->left, &aux); + code(ASRET, NULL, p, NULL); + break; + case OBSWITCH: + swtch(rhs(np->left, &aux)); + break; + default: + rhs(np, &aux); + break; + } + return NULL; +} + +/* + * This is strongly influenced by + * http://plan9.bell-labs.com/sys/doc/compiler.ps (/sys/doc/compiler.ps) + * calculate addresability as follows + * AUTO => 11 value+fp + * REG => 13 reg + * STATIC => 12 (value) + * CONST => 20 $value + */ +Node * +sethi(Node *np) +{ + Node *lp, *rp; + + if (!np) + return np; + + np->complex = 0; + np->address = 0; + lp = np->left; + rp = np->right; + switch (np->op) { + case OAUTO: + np->address = 11; + break; + case OREG: + np->address = 13; + break; + case OMEM: + np->address = 12; + break; + case OCONST: + np->address = 20; + break; + default: + sethi(lp); + sethi(rp); + break; + } + + if (np->address > 10) + return np; + if (lp) + np->complex = lp->complex; + if (rp) { + int d = np->complex - rp->complex; + + if (d == 0) + ++np->complex; + else if (d < 0) + np->complex = rp->complex; + } + if (np->complex == 0) + ++np->complex; + return np; +} diff --git a/src/cc2/target/z80-scc/code.c b/src/cc2/target/z80-scc/code.c @@ -0,0 +1,229 @@ +static char sccsid[] = "@(#) ./cc2/arch/z80/code.c"; + +#include <stdio.h> +#include <stdlib.h> + +#include <scc/cstd.h> +#include <scc/scc.h> + +#include "arch.h" +#include "../../cc2.h" + +enum segment { + CODESEG, + DATASEG, + BSSSEG, + NOSEG +}; + +static int curseg = NOSEG; +static unsigned long offpar, offvar; + +static void +segment(int seg) +{ + static char *txt[] = { + [CODESEG] = "\tCSEG\n", + [DATASEG] = "\tDSEG\n", + [BSSSEG] = "\tASEG\n", + }; + + if (seg == curseg) + return; + fputs(txt[seg], stdout); + curseg = seg; +} + +static char * +symname(Symbol *sym) +{ + static char name[INTIDENTSIZ+1]; + + if (sym->name) { + switch (sym->kind) { + case SGLOB: + case SEXTRN: + snprintf(name, sizeof(name), "_%s", sym->name); + return name; + case SPRIV: + return sym->name; + } + } + + sprintf(name, ".%d", sym->numid); + + return name; +} + +static void +label(Symbol *sym) +{ + int seg; + char *name = symname(sym); + + if (sym->type.flags & FUNF) + seg = CODESEG; + else if (sym->type.flags & INITF) + seg = DATASEG; + else + seg = BSSSEG; + segment(seg); + + switch (sym->kind) { + case SEXTRN: + printf("\tEXTRN\t%s\n", name); + return; + case SGLOB: + printf("\tPUBLIC\t%s\n", name); + break; + } + + printf("%s:\n", name); +} + +static void +emitconst(Node *np) +{ + switch (np->type.size) { + case 1: + printf("%d", (int) np->u.i & 0xFF); + break; + case 2: + printf("%d", (int) np->u.i & 0xFFFF); + break; + case 4: + printf("%ld", (long) np->u.i & 0xFFFFFFFF); + break; + default: + abort(); + } +} + +static void +emittree(Node *np) +{ + if (!np) + return; + + switch (np->op) { + case OSTRING: + printf("\"%s\"", np->u.s); + free(np->u.s); + np->u.s = NULL; + break; + case OCONST: + emitconst(np); + break; + case OADDR: + emittree(np->left); + break; + case OMEM: + fputs(symname(np->u.sym), stdout); + break; + default: + emittree(np->left); + printf(" %c ", np->op); + emittree(np->right); + break; + } +} + +static void +size2asm(Type *tp) +{ + char *s; + + /* + * In z80 we can ignore the alignment + */ + if (tp->flags & STRF) { + s = "\tDB\t"; + } else { + switch (tp->size) { + case 1: + s = "\tDB\t"; + break; + case 2: + s = "\tDW\t"; + break; + case 4: + s = "\tDD\t"; + break; + default: + s = "\tDS\t%lu,"; + break; + } + } + printf(s, tp->size); +} + +void +newfun() +{ + offpar = offvar = 0; +} + +void +defpar(Symbol *sym) +{ + unsigned long align, size; + + if (sym->kind != SREG && sym->kind != SAUTO) + return; + align = sym->type.align; + size = sym->type.size; + + offpar -= align-1 & ~align; + sym->u.off = offpar; + offpar -= size; + sym->kind = SAUTO; +} + +void +defvar(Symbol *sym) +{ + unsigned long align, size; + + if (sym->kind != SREG && sym->kind != SAUTO) + return; + align = sym->type.align; + size = sym->type.size; + + offvar += align-1 & ~align; + sym->u.off = offvar; + offvar += size; + sym->kind = SAUTO; +} + +void +defglobal(Symbol *sym) +{ + label(sym); + if (sym->kind == SEXTRN || (sym->type.flags & INITF)) + return; + size2asm(&sym->type); + puts("0"); +} + +void +data(Node *np) +{ + size2asm(&np->type); + emittree(np); + putchar('\n'); +} + +void +writeout(void) +{ +} + +void +endinit(void) +{ +} + +void +getbblocks(void) +{ +} diff --git a/src/cc2/target/z80-scc/optm.c b/src/cc2/target/z80-scc/optm.c @@ -0,0 +1,11 @@ +static char sccsid[] = "@(#) ./cc2/arch/z80/optm.c"; + +#include <scc/scc.h> + +#include "../../cc2.h" + +Node * +optm_dep(Node *np) +{ + return np; +} diff --git a/src/cc2/target/z80-scc/target.mk b/src/cc2/target/z80-scc/target.mk @@ -0,0 +1,8 @@ +OBJ-z80-scc = $(OBJS) \ + target/z80-scc/cgen.o \ + target/z80-scc/optm.o \ + target/z80-scc/code.o \ + target/z80-scc/types.o \ + +$(LIBEXEC)/cc2-z80-scc: $(OBJ-z80-scc) + $(CC) $(SCC_LDFLAGS) $(OBJ-z80-scc) -lscc -o $@ diff --git a/src/cc2/target/z80-scc/types.c b/src/cc2/target/z80-scc/types.c @@ -0,0 +1,95 @@ +static char sccsid[] = "@(#) ./cc2/arch/z80/types.c"; + +#include <scc/scc.h> + +#include "../../cc2.h" + + +Type int8type = { + .flags = SIGNF | INTF, + .size = 1, + .align = 1 +}; + +Type int16type = { + .flags = SIGNF | INTF, + .size = 2, + .align = 1 +}; + +Type int32type = { + .flags = SIGNF | INTF, + .size = 4, + .align = 1 +}; + +Type int64type = { + .flags = SIGNF | INTF, + .size = 8, + .align = 1 +}; + +Type uint8type = { + .flags = INTF, + .size = 1, + .align = 1 +}; + +Type uint16type = { + .flags = INTF, + .size = 2, + .align = 1 +}; + +Type uint32type = { + .flags = INTF, + .size = 4, + .align = 1 +}; + +Type uint64type = { + .flags = INTF, + .size = 8, + .align = 1 +}; + +Type ptrtype = { + .flags = INTF, + .size = 2, + .align = 1 +}; + +Type booltype = { + .flags = INTF, + .size = 1, + .align = 1 +}; + +Type float32type = { + .flags = FLOATF, + .size = 4, + .align = 1 +}; + +Type float64type = { + .flags = FLOATF, + .size = 4, + .align = 1 +}; + +Type float80type = { + .flags = FLOATF, + .size = 4, + .align = 1 +}; + +Type voidtype = { + .size = 0, + .align = 0 +}; + +/* this types is not going to be used in this arch */ +Type arg_type = { + .size = 0, + .align = 0 +}; diff --git a/src/driver/Makefile b/src/driver/Makefile @@ -0,0 +1,8 @@ +.POSIX: + +DRIVER = posix +PROJECTDIR = ../.. +include $(PROJECTDIR)/scripts/rules.mk + +all dep clean: + +@cd $(DRIVER) && $(MAKE) $@ diff --git a/src/driver/posix/Makefile b/src/driver/posix/Makefile @@ -0,0 +1,40 @@ +.POSIX: + +PROJECTDIR = ../.. +include $(PROJECTDIR)/rules.mk + +# SYSLST is a list of backend-arch-abi-sys. First +# element of the list becomes the default target + +SYSLST = amd64-sysv-linux-elf z80-scc-none-none \ + i386-sysv-linux-elf amd64-sysv-openbsd-elf + +STDCFLAGS = + +TARGETS = $(BINDIR)/scc $(BINDIR)/scpp + +all: $(TARGETS) + +$(BINDIR)/scc: scc.o + $(CC) $(SCC_LDFLAGS) scc.o -lscc -o $@ + +$(BINDIR)/scpp: cpp.sh config.h + set -x ;\ + trap "rm -f $$$$.sh" 0 2 3;\ + rm -f $@ ;\ + sed "s%@PREFIX@%$(PREFIX)%" < cpp.sh > $$$$.sh && \ + chmod +x $$$$.sh && \ + mv $$$$.sh $@ + +config.h: + PREFIX=$(PREFIX) ./config.sh $(SYSLST) + +dep: + $(PROJECTDIR)/mkdep.sh + +clean: + rm -f scc scpp *.o + rm -f $(TARGETS) + rm -f config.h + +include deps.mk diff --git a/src/driver/posix/config.h b/src/driver/posix/config.h @@ -0,0 +1,5 @@ +#define PREFIX "/home/robvar01/src/tools/scc/driver/posix/../../root" +#define ARCH "amd64" +#define SYS "linux" +#define ABI "sysv" +#define FORMAT "elf" diff --git a/driver/posix/config.sh b/src/driver/posix/config.sh diff --git a/driver/posix/cpp.sh b/src/driver/posix/cpp.sh diff --git a/driver/posix/deps.mk b/src/driver/posix/deps.mk diff --git a/driver/posix/scc.c b/src/driver/posix/scc.c diff --git a/src/ld/Makefile b/src/ld/Makefile @@ -0,0 +1,21 @@ +.POSIX: + +PROJECTDIR = ../.. +include $(PROJECTDIR)/scripts/rules.mk + +OBJS = main.o \ + coff32.o \ + obj.o \ + +TARGET = $(BINDIR)/ld + +all: $(TARGET) + +$(TARGET): $(LIBDIR)/libcoff32.a $(LIBDIR)/libscc.a + +$(TARGET): $(OBJS) + $(CC) $(SCC_LDFLAGS) $(OBJS) -lcoff32 -lscc -o $@ + +dep: inc-dep + +include deps.mk diff --git a/src/ld/coff32.c b/src/ld/coff32.c @@ -0,0 +1,403 @@ +static char sccsid[] = "@(#) ./ld/coff32.c"; + +#include <assert.h> +#include <ctype.h> +#include <errno.h> +#include <limits.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <scc/coff32/aouthdr.h> +#include <scc/coff32/filehdr.h> +#include <scc/coff32/scnhdr.h> +#include <scc/coff32/syms.h> +#include <scc/coff32/coff32.h> +#include <scc/scc.h> +#include "ld.h" + +#define NUMSCN_MAX 65536 +#define NUMENT_MAX 2147483648 + +static long textpc = 0x1000; + +/* + * check overflow in: off + ptr + nitem*size + */ +static char * +symname(Obj *obj, SYMENT *ent) +{ + long off; + + if (ent->n_zeroes != 0) + return ent->n_name; + + off = ent->n_offset; + if (off >= obj->strsiz) { + fprintf(stderr, + "ld: invalid offset in symbol table: %zd\n", off); + return ""; + } + + return &obj->strtbl[off]; +} + +static int +readstr(Obj *obj, long off) +{ + unsigned char buff[4]; + char *str; + size_t siz; + + if (fseek(obj->fp, off, SEEK_SET) == EOF) + return -1; + + if (fread(buff, 4, 1, obj->fp) != 1) + return -1; + + (*obj->unpack)(buff, "l", &siz); + + siz -= 4; + if (siz == 0) { + obj->strtbl = NULL; + obj->strsiz = 0; + return 0; + } + + if (siz > SIZE_MAX || (str = malloc(siz)) == NULL) + outmem(); + + if (fread(str, siz, 1, obj->fp) != 1) + return -1; + + obj->strtbl = str; + obj->strsiz = siz; + + return 0; +} + +static int +readsects(Obj *obj, long off) +{ + unsigned a, nsec, i; + unsigned char buff[SCNHSZ]; + SCNHDR *scns, *p; + FILHDR *hdr; + Symbol *sym; + Section *sp; + + hdr = obj->filhdr; + nsec = hdr->f_nscns; + + scns = NULL; + if (nsec <= SIZE_MAX / sizeof(*scns)) + scns = malloc(nsec * sizeof(*scns)); + if (!scns) + outmem(); + obj->scnhdr = scns; + + if (fseek(obj->fp, off, SEEK_SET) == EOF) + return -1; + + a = obj->align - 1; + for (i = 0; i < nsec; ++i) { + p = &scns[i]; + if (fread(buff, SCNHSZ, 1, obj->fp) != 1) + return -1; + coff32_unpack_scn(obj->unpack, buff, p); + sp = slookup(p->s_name); + p->s_vaddr = sp->base + sp->size; + sp->size += p->s_size; + } + + return 0; +} + +static int +readents(Obj *obj, long off) +{ + SYMENT *ent, *ents; + SCNHDR *scn, *scns = obj->scnhdr; + FILHDR *hdr = obj->filhdr;; + long nsyms = hdr->f_nsyms; + unsigned nsect; + unsigned char buff[SYMESZ]; + char *s; + int aux; + Symbol *sym; + + + if (fseek(obj->fp, off, SEEK_SET) == EOF) + return -1; + + ents = NULL; + if (nsyms <= SIZE_MAX/sizeof(SYMENT)) + ents = malloc((nsyms * sizeof(SYMENT))); + if (!ents) + outmem(); + obj->enthdr = ents; + + aux = 0; + for (ent = ents; ent < &ents[nsyms]; ++ent) { + if (fread(buff, SYMESZ, 1, obj->fp) != 1) + return -1; + coff32_unpack_ent(obj->unpack, buff, ent); + s = ent->n_name; + if (!s[0] && !s[1] && !s[2] && !s[3]) + (*obj->unpack)(buff, "ll", &ent->n_zeroes, &ent->n_offset); + + if (aux > 0) { + aux--; + continue; + } + aux = ent->n_numaux; + + scn = NULL; + switch (ent->n_scnum) { + case N_DEBUG: + continue; + case N_ABS: + break; + case N_UNDEF: + /* TODO: deal wth common blocks */ + break; + default: + nsect = ent->n_scnum-1; + if (nsect >= hdr->f_nscns) + corrupted(obj->fname, obj->member); + scn = &scns[nsect]; + ent->n_value += scn->s_vaddr; + } + + if (ent->n_sclass == C_EXT && ent->n_scnum != N_UNDEF) { + Symbol *sym = lookup(symname(obj, ent), INSTALL); + + if (sym->flags & SDEFINED) { + redefined(obj, sym); + } else { + sym->flags |= SDEFINED; + sym->where = obj; + if (scn) + sym->section = slookup(scn->s_name); + } + } + } + + return 0; +} + +static long +fileptr(long off, long ptr, long nitem, long size) +{ + if (off < 0 || ptr < 0 || nitem < 0 || size < 0) + return -1; + + if (off > LONG_MAX - ptr) + return -1; + off += ptr; + + if (size > 0) { + if (nitem > LONG_MAX / size) + return -1; + size *= nitem; + } + + if (off > LONG_MAX - size) + return -1; + off += size; + + return off; +} + +Obj * +load(Obj *obj) +{ + unsigned char buff[FILHSZ]; + FILHDR *hdr; + char *strtbl; + long symoff, secoff, stroff, pos; + + pos = ftell(obj->fp); + if (fread(buff, FILHSZ, 1, obj->fp) != 1) + goto bad_file; + + if ((hdr = malloc(sizeof(*hdr))) == NULL) + outmem(); + coff32_unpack_hdr(obj->unpack, buff, hdr); + obj->filhdr = hdr; + + stroff = fileptr(pos, hdr->f_symptr, hdr->f_nsyms, SYMESZ); + symoff = fileptr(pos, hdr->f_symptr, 0, 0); + secoff = fileptr(pos, hdr->f_opthdr, 1, FILHSZ); + + if (stroff < 0 || symoff < 0 || secoff < 0) + goto bad_file; + + if (readstr(obj, stroff) < 0) + goto bad_file; + if (readsects(obj, secoff) < 0) + goto bad_file; + if (readents(obj, symoff) < 0) + goto bad_file; + return add(obj); + +bad_file: + fprintf(stderr, + "ld: %s: %s\n", + obj->fname, + (ferror(obj->fp)) ? strerror(errno) : "corrupted file"); + exit(EXIT_FAILURE); +} + +Obj * +probe(char *fname, char *member, FILE *fp) +{ + int c; + int c1, c2; + long pos; + unsigned short magic; + unsigned align; + int (*unpack)(unsigned char *, char *, ...); + int (*pack)(unsigned char *, char *, ...); + Obj *obj; + + pos = ftell(fp); + c1 = getc(fp); + c2 = getc(fp); + fseek(fp, pos, SEEK_SET); + + if (ferror(fp)) + die("ld: %s: %s", fname, strerror(errno)); + + if (c1 == EOF || c2 == EOF) + return 0; + magic = c1 | c2 << 8; + + switch (magic) { + case COFF_I386MAGIC: + case COFF_Z80MAGIC: + unpack = lunpack; + pack = lpack; + align = 2; + break; + default: + return NULL; + } + + obj = newobj(fname, member, fp); + obj->unpack = unpack; + obj->align = align; + obj->offset = pos; + + return obj; +} + +static void +wrhdr(FILE *fp) +{ + FILHDR hdr; + Section *sp; + unsigned char buff[FILHSZ]; + + if (numsects > NUMSCN_MAX || numsymbols > NUMENT_MAX) { + fprintf(stderr, "ld: too many symbols or sections\n"); + exit(EXIT_FAILURE); + } + + /* + * we set the timestamp to 0 to make the output + * reproductible and to avoid a not standard use + * of time() + */ + hdr.f_symptr = 0; + hdr.f_magic = COFF_Z80MAGIC; + hdr.f_nscns = numsects; + hdr.f_symptr = 0; + hdr.f_timdat = 0; + hdr.f_nsyms = 0; + hdr.f_opthdr = AOUTSZ; + hdr.f_flags = F_EXEC | F_AR32WR; /* TODO: set the correct endianess */ + + if (!sflag) { + hdr.f_symptr = 0; /* TODO: set correct value here */ + hdr.f_flags |= F_SYMS; + hdr.f_nsyms = numsymbols; + } + + coff32_pack_hdr(lpack, buff, &hdr); + fwrite(buff, FILHSZ, 1, fp); +} + +static void +wraout(FILE *fp) +{ + AOUTHDR aout; + unsigned char buff[AOUTSZ]; + Symbol *sym; + long addr; + + if ((sym = lookup(entry, NOINSTALL)) != NULL) { + addr = sym->value; + } else { + fprintf(stderr, + "ld: warning: cannot find entry symbol '%s'; defaulting to 0\n", + entry); + addr = 0; + } + + aout.magic = ZMAGIC; + aout.vstamp = 0; + aout.entry = addr; + aout.tsize = tsize; + aout.dsize = dsize; + aout.bsize = bsize; + aout.text_start = textpc; + aout.data_start = textpc + dsize; + + coff32_pack_aout(lpack, buff, &aout); + fwrite(buff, AOUTSZ, 1, fp); +} + +static void +wrscn(FILE *fp, Section *sp, long pc) +{ + SCNHDR scn; + unsigned char buff[SCNHSZ]; + + strcpy(scn.s_name, sp->name); + scn.s_paddr = pc; + scn.s_vaddr = pc; + scn.s_size = sp->size; + scn.s_scnptr = 0; /* TODO: file ptr */ + scn.s_relptr = 0; + scn.s_lnnoptr = 0; + scn.s_nrelloc = 0; + scn.s_nlnno = 0; + scn.s_flags = 0; /* TODO: Add flags */ + + coff32_pack_scn(lpack, buff, &scn); + fwrite(buff, SCNHSZ, 1, fp); +} + +void +writeout(FILE *fp) +{ + Section *sp; + long pc = textpc; + + wrhdr(fp); + wraout(fp); + + for (sp = sectlst; sp; sp = sp->next) { + wrscn(fp, sp, pc); + pc += sp->size; + } + + /* TODO: run over all the files */ + + if (fflush(fp) == EOF) { + perror("ld: error writing output file"); + exit(EXIT_FAILURE); + } +} diff --git a/src/ld/deps.mk b/src/ld/deps.mk @@ -0,0 +1,15 @@ + +#deps +coff32.o: $(INCDIR)/scc/scc/coff32/aouthdr.h +coff32.o: $(INCDIR)/scc/scc/coff32/coff32.h +coff32.o: $(INCDIR)/scc/scc/coff32/filehdr.h +coff32.o: $(INCDIR)/scc/scc/coff32/scnhdr.h +coff32.o: $(INCDIR)/scc/scc/coff32/syms.h +coff32.o: $(INCDIR)/scc/scc/scc.h +coff32.o: ld.h +main.o: $(INCDIR)/scc/scc/ar.h +main.o: $(INCDIR)/scc/scc/scc.h +main.o: $(INCDIR)/scc/scc/syslibs.h +main.o: ld.h +obj.o: $(INCDIR)/scc/scc/scc.h +obj.o: ld.h diff --git a/ld/ld.h b/src/ld/ld.h diff --git a/src/ld/main.c b/src/ld/main.c @@ -0,0 +1,288 @@ +static char sccsid[] = "@(#) ./ld/main.c"; + +#include <ctype.h> +#include <errno.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <scc/scc.h> +#include <scc/ar.h> +#include <scc/syslibs.h> +#include "ld.h" + +char *output = "a.out", *entry = "start", *datasiz; +int pass; +int sflag; /* discard all the symbols */ +int xflag; /* discard local symbols */ +int Xflag; /* discard locals starting with 'L' */ +int rflag; /* preserve relocation bits */ +int dflag; /* define common even with rflag */ +int gflag; /* preserve debug symbols */ + +static int done; + +void +redefined(Obj *obj, Symbol *sym) +{ + /* TODO: add infotmation about where it is defined */ + fprintf(stderr, + "ld: %s: redifinition of symbol '%s'\n", + obj->fname, sym->name); +} + +void +corrupted(char *fname, char *member) +{ + char *fmt; + + fmt = (member) ? + "ld: %s(%s): corrupted file\n" : "ld: %s: corrupted file\n"; + fprintf(stderr, fmt, fname, member); + exit(EXIT_FAILURE); +} + +void +outmem(void) +{ + fputs("ld: out of memory\n", stderr); + exit(EXIT_FAILURE); +} + +static void +cleanup(void) +{ + if (!done) + remove(output); +} + +static int +object(char *fname, char *member, FILE *fp) +{ + Obj *obj; + + obj = probe(fname, member, fp); + if (!obj) + return 0; + load(obj); + + return 1; +} + +static char * +getfname(struct ar_hdr *hdr, char *dst) +{ + char *p; + int i; + + memcpy(dst, hdr->ar_name, SARNAM); + dst[SARNAM] = '\0'; + + for (i = SARNAM-1; i >= 0; i--) { + if (dst[i] != ' ' && dst[i] != '/') + break; + dst[i] = '\0'; + } + return dst; +} + +static void +ar(char *fname, FILE *fp) +{ + struct ar_hdr hdr; + long pos, siz; + char member[SARNAM+1]; + + if (fseek(fp, SARMAG, SEEK_SET) == EOF) + goto file_error; + + while (fread(&hdr, sizeof(hdr), 1, fp) == 1) { + if (strncmp(hdr.ar_fmag, ARFMAG, sizeof(hdr.ar_fmag))) + corrupted(fname, NULL); + + siz = 0; + sscanf(hdr.ar_size, "%10ld", &siz); + if (siz & 1) + siz++; + if (siz == 0) + corrupted(fname, NULL); + + pos = ftell(fp); + if (pos == -1 || pos > LONG_MAX - siz) { + fprintf(stderr, + "ld: %s(%s): overflow in size of archive", + fname, member); + exit(EXIT_FAILURE); + } + pos += siz; + + getfname(&hdr, member); + object(fname, member, fp); + if (fseek(fp, pos, SEEK_SET) == EOF) + break; + } + +file_error: + if (ferror(fp)) { + fprintf(stderr, "ld: %s: %s\n", fname, strerror(errno)); + exit(EXIT_FAILURE); + } +} + +static int +archive(char *fname, FILE *fp) +{ + char magic[SARMAG]; + fpos_t pos; + + fgetpos(fp, &pos); + fread(magic, SARMAG, 1, fp); + fsetpos(fp, &pos); + + if (ferror(fp)) + return 0; + if (strncmp(magic, ARMAG, SARMAG) != 0) + return 0; + + ar(fname, fp); + return 1; +} + +static void +pass1(int argc, char *argv[]) +{ + FILE *fp; + char *s; + + while ((s = *argv++) != NULL) { + if ((fp = fopen(s, "rb")) == NULL) { + fprintf(stderr, "ld: %s: %s\n", s, strerror(errno)); + exit(EXIT_FAILURE); + } + if (!object(s, NULL, fp) && !archive(s, fp)) { + fprintf(stderr, "ld: %s: File format not recognized\n", s); + exit(EXIT_FAILURE); + } + fclose(fp); + } +} + +static void +pass2(int argc, char *argv[]) +{ + FILE *fp; + + if ((fp = fopen(output, "wb")) != NULL) { + writeout(fp); + if (fclose(fp) != EOF) + return; + } + + fprintf(stderr, "ld: %s: %s\n", output, strerror(errno)); + exit(EXIT_FAILURE); +} + +static void +usage(void) +{ + fputs("usage: ld [options] file ...\n", stderr); + exit(1); +} + +static void +Lpath(char *path) +{ + char **bp; + + for (bp = syslibs; bp < &syslibs[MAX_LIB_PATHS] && *bp; ++bp) + ; + if (bp == &syslibs[MAX_LIB_PATHS]) { + fputs("ld: too many -L options\n", stderr); + exit(1); + } + *bp = path; +} + +int +main(int argc, char *argv[]) +{ + char *cp, **p; + + for (--argc; *++argv; --argc) { + if (argv[0][0] != '-' || argv[0][1] == 'l') + break; + if (argv[0][1] == '-') { + --argc, ++argv; + break; + } + for (cp = &argv[0][1]; *cp; ++cp) { + switch (*cp) { + case 's': + sflag = 1; + break; + case 'x': + xflag = 1; + break; + case 'X': + Xflag = 1; + break; + case 'r': + rflag = 1; + break; + case 'd': + dflag = 1; + break; + case 'i': + case 'n': + /* TODO */ + break; + case 'L': + if (argc == 0) + goto usage; + ++argv, --argc; + Lpath(*argv); + break; + case 'u': + if (argc == 0) + goto usage; + ++argv, --argc; + lookup(*argv, INSTALL); + break; + case 'o': + if (argc == 0) + goto usage; + ++argv, --argc; + output = *argv; + break; + case 'e': + if (argc == 0) + goto usage; + ++argv, --argc; + entry = *argv; + break; + case 'D': + if (argc == 0) + goto usage; + ++argv, --argc; + datasiz = *argv; + break; + default: + usage: + usage(); + } + } + } + + if (argc == 0) + usage(); + + atexit(cleanup); + + pass1(argc, argv); + pass2(argc, argv); + + done = 1; + + return 0; +} diff --git a/src/ld/obj.c b/src/ld/obj.c @@ -0,0 +1,153 @@ +static char sccsid[] = "@(#) ./ld/obj.c"; + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <scc/scc.h> +#include "ld.h" + +#define NR_SYM_HASH 64 + +TUINT tsize, dsize, bsize; + +Obj *objlst; +static Obj *objtail; + +long numsects, numsymbols; +static Symbol *secttail; +static Symbol *symtbl[NR_SYM_HASH]; + +Section *sectlst; + +Obj * +add(Obj *obj) +{ + obj->next = NULL; + + if (!objlst) { + objtail = objlst = obj; + } else { + objtail->next = obj; + objtail = obj; + } +} + +void +delobj(Obj *obj) +{ + free(obj->strtbl); + free(obj->scnhdr); + free(obj->filhdr); + free(obj->fname); + free(obj->member); + free(obj); +} + +Obj * +newobj(char *fname, char *member, FILE *fp) +{ + Obj *obj; + char *s, *t; + size_t len; + + len = strlen(fname); + obj = malloc(sizeof(*obj)); + s = malloc(len) + 1; + if (!obj || !s) + outmem(); + memset(obj, 0, sizeof(*obj)); + obj->fname = memcpy(s, fname, len); + + if (!member) { + obj->member = NULL; + } else { + len = strlen(member) + 1; + if ((s = malloc(len)) == NULL) + outmem(); + obj->member = memcpy(s, member, len); + } + + obj->fp = fp; + if ((obj->offset = ftell(fp)) == EOF) { + fprintf(stderr, "ld: %s: %s\n", fname, strerror(errno)); + exit(1); + } + + return obj; +} + +Section * +slookup(char *name) +{ + char *s; + Section *prev, *sp; + size_t len = strlen(name); + + for (prev = sp = sectlst; sp; prev = sp, sp = sp->next) { + if (!memcmp(sp->name, name, len)) + return sp; + } + + sp = malloc(sizeof(*sp)); + s = malloc(len); + if (!sp || !s) + outmem(); + sp->name = s; + sp->base = 0; + sp->size = 0; + sp->next = NULL; + + if (!prev) + sectlst = sp; + else + prev->next = sp; + numsects++; + + return sp; +} + +static unsigned +hash(char *s) +{ + unsigned h, c; + + for (h = 0; c = *s; ++s) + h = h*33 ^ c; + return h & NR_SYM_HASH-1; +} + +Symbol * +lookup(char *name, int install) +{ + unsigned h; + char *s; + size_t len; + Symbol *sym; + + h = hash(name); + for (sym = symtbl[h]; sym; sym = sym->hash) { + s = sym->name; + if (*name == *s && !strcmp(name, s)) + return sym; + } + + if (!install) + return NULL; + + len = strlen(name) + 1; + sym = malloc(sizeof(*sym)); + s = malloc(len); + if (!sym || !s) + outmem(); + memset(sym, 0, sizeof(*sym)); + memcpy(s, name, len); + + sym->hash = symtbl[h]; + symtbl[h] = sym; + sym->name = s; + numsymbols++; + + return sym; +} diff --git a/lib/c/.gitignore b/src/libc/.gitignore diff --git a/src/libc/Makefile b/src/libc/Makefile @@ -0,0 +1,30 @@ +.POSIX: +PROJECTDIR =../.. +include $(PROJECTDIR)/scripts/rules.mk + +MORECFLAGS = -I$(INCDIR) -I$(INCDIR)/bits/$(SYS) -I$(INCDIR)/bits/$(ARCH) +TARGET = $(CRTDIR)/$(ARCH)-$(SYS)/libc.a +DIRS = arch\ + assert\ + ctype\ + locale\ + stdio\ + stdlib\ + string\ + time\ + +all: $(DIRS) + +@$(MAKE) $(TARGET) + +$(DIRS): FORCE + +@cd $@ && $(MAKE) + +objlst: FORCE + ./mklst $(TARGET) + +$(TARGET): objlst + xargs $(AR) $(ARFLAGS) $@ < objlst + +clean: + $(FORALL) + rm -f objlst diff --git a/lib/c/arch/.gitignore b/src/libc/arch/.gitignore diff --git a/lib/c/arch/Makefile b/src/libc/arch/Makefile diff --git a/lib/c/arch/amd64/Makefile b/src/libc/arch/amd64/Makefile diff --git a/lib/c/arch/amd64/dragonfly/.gitignore b/src/libc/arch/amd64/dragonfly/.gitignore diff --git a/lib/c/arch/amd64/dragonfly/Makefile b/src/libc/arch/amd64/dragonfly/Makefile diff --git a/lib/c/arch/amd64/dragonfly/_getheap.s b/src/libc/arch/amd64/dragonfly/_getheap.s diff --git a/lib/c/arch/amd64/dragonfly/_sigaction.c b/src/libc/arch/amd64/dragonfly/_sigaction.c diff --git a/lib/c/arch/amd64/dragonfly/_tzone.c b/src/libc/arch/amd64/dragonfly/_tzone.c diff --git a/lib/c/arch/amd64/dragonfly/gensys.sh b/src/libc/arch/amd64/dragonfly/gensys.sh diff --git a/lib/c/arch/amd64/dragonfly/getenv.c b/src/libc/arch/amd64/dragonfly/getenv.c diff --git a/lib/c/arch/amd64/dragonfly/raise.c b/src/libc/arch/amd64/dragonfly/raise.c diff --git a/lib/c/arch/amd64/dragonfly/signal.c b/src/libc/arch/amd64/dragonfly/signal.c diff --git a/lib/c/arch/amd64/dragonfly/syscall.lst b/src/libc/arch/amd64/dragonfly/syscall.lst diff --git a/lib/c/arch/amd64/dragonfly/time.c b/src/libc/arch/amd64/dragonfly/time.c diff --git a/lib/c/arch/amd64/linux/.gitignore b/src/libc/arch/amd64/linux/.gitignore diff --git a/lib/c/arch/amd64/linux/Makefile b/src/libc/arch/amd64/linux/Makefile diff --git a/lib/c/arch/amd64/linux/_cerrno.s b/src/libc/arch/amd64/linux/_cerrno.s diff --git a/lib/c/arch/amd64/linux/_getheap.s b/src/libc/arch/amd64/linux/_getheap.s diff --git a/lib/c/arch/amd64/linux/_sigaction.c b/src/libc/arch/amd64/linux/_sigaction.c diff --git a/lib/c/arch/amd64/linux/_tzone.c b/src/libc/arch/amd64/linux/_tzone.c diff --git a/lib/c/arch/amd64/linux/errno.lst b/src/libc/arch/amd64/linux/errno.lst diff --git a/lib/c/arch/amd64/linux/gensys.sh b/src/libc/arch/amd64/linux/gensys.sh diff --git a/lib/c/arch/amd64/linux/getenv.c b/src/libc/arch/amd64/linux/getenv.c diff --git a/lib/c/arch/amd64/linux/raise.c b/src/libc/arch/amd64/linux/raise.c diff --git a/lib/c/arch/amd64/linux/signal.c b/src/libc/arch/amd64/linux/signal.c diff --git a/lib/c/arch/amd64/linux/syscall.lst b/src/libc/arch/amd64/linux/syscall.lst diff --git a/lib/c/arch/amd64/linux/time.c b/src/libc/arch/amd64/linux/time.c diff --git a/lib/c/arch/amd64/longjmp.s b/src/libc/arch/amd64/longjmp.s diff --git a/lib/c/arch/amd64/netbsd/.gitignore b/src/libc/arch/amd64/netbsd/.gitignore diff --git a/lib/c/arch/amd64/netbsd/Makefile b/src/libc/arch/amd64/netbsd/Makefile diff --git a/lib/c/arch/amd64/netbsd/_getheap.s b/src/libc/arch/amd64/netbsd/_getheap.s diff --git a/lib/c/arch/amd64/netbsd/_setcontext.s b/src/libc/arch/amd64/netbsd/_setcontext.s diff --git a/lib/c/arch/amd64/netbsd/_sigaction.c b/src/libc/arch/amd64/netbsd/_sigaction.c diff --git a/lib/c/arch/amd64/netbsd/_sigaction2.s b/src/libc/arch/amd64/netbsd/_sigaction2.s diff --git a/lib/c/arch/amd64/netbsd/_tzone.c b/src/libc/arch/amd64/netbsd/_tzone.c diff --git a/lib/c/arch/amd64/netbsd/errno.lst b/src/libc/arch/amd64/netbsd/errno.lst diff --git a/lib/c/arch/amd64/netbsd/gensys.sh b/src/libc/arch/amd64/netbsd/gensys.sh diff --git a/lib/c/arch/amd64/netbsd/getenv.c b/src/libc/arch/amd64/netbsd/getenv.c diff --git a/lib/c/arch/amd64/netbsd/raise.c b/src/libc/arch/amd64/netbsd/raise.c diff --git a/lib/c/arch/amd64/netbsd/signal.c b/src/libc/arch/amd64/netbsd/signal.c diff --git a/lib/c/arch/amd64/netbsd/syscall.lst b/src/libc/arch/amd64/netbsd/syscall.lst diff --git a/lib/c/arch/amd64/netbsd/time.c b/src/libc/arch/amd64/netbsd/time.c diff --git a/lib/c/arch/amd64/openbsd/.gitignore b/src/libc/arch/amd64/openbsd/.gitignore diff --git a/lib/c/arch/amd64/openbsd/Makefile b/src/libc/arch/amd64/openbsd/Makefile diff --git a/lib/c/arch/amd64/openbsd/_getheap.s b/src/libc/arch/amd64/openbsd/_getheap.s diff --git a/lib/c/arch/amd64/openbsd/_sigaction.c b/src/libc/arch/amd64/openbsd/_sigaction.c diff --git a/lib/c/arch/amd64/openbsd/_tzone.c b/src/libc/arch/amd64/openbsd/_tzone.c diff --git a/lib/c/arch/amd64/openbsd/errno.lst b/src/libc/arch/amd64/openbsd/errno.lst diff --git a/lib/c/arch/amd64/openbsd/gensys.sh b/src/libc/arch/amd64/openbsd/gensys.sh diff --git a/lib/c/arch/amd64/openbsd/getenv.c b/src/libc/arch/amd64/openbsd/getenv.c diff --git a/lib/c/arch/amd64/openbsd/raise.c b/src/libc/arch/amd64/openbsd/raise.c diff --git a/lib/c/arch/amd64/openbsd/signal.c b/src/libc/arch/amd64/openbsd/signal.c diff --git a/lib/c/arch/amd64/openbsd/syscall.lst b/src/libc/arch/amd64/openbsd/syscall.lst diff --git a/lib/c/arch/amd64/openbsd/time.c b/src/libc/arch/amd64/openbsd/time.c diff --git a/lib/c/arch/amd64/setjmp.s b/src/libc/arch/amd64/setjmp.s diff --git a/lib/c/arch/arm32/Makefile b/src/libc/arch/arm32/Makefile diff --git a/lib/c/arch/arm32/linux/.gitignore b/src/libc/arch/arm32/linux/.gitignore diff --git a/lib/c/arch/arm32/linux/Makefile b/src/libc/arch/arm32/linux/Makefile diff --git a/lib/c/arch/arm32/linux/_cerrno.s b/src/libc/arch/arm32/linux/_cerrno.s diff --git a/lib/c/arch/arm32/linux/_getheap.s b/src/libc/arch/arm32/linux/_getheap.s diff --git a/lib/c/arch/arm32/linux/_open.c b/src/libc/arch/arm32/linux/_open.c diff --git a/lib/c/arch/arm32/linux/_tzone.c b/src/libc/arch/arm32/linux/_tzone.c diff --git a/lib/c/arch/arm32/linux/gensys.sh b/src/libc/arch/arm32/linux/gensys.sh diff --git a/lib/c/arch/arm32/linux/getenv.c b/src/libc/arch/arm32/linux/getenv.c diff --git a/lib/c/arch/arm32/linux/raise.c b/src/libc/arch/arm32/linux/raise.c diff --git a/lib/c/arch/arm32/linux/signal.c b/src/libc/arch/arm32/linux/signal.c diff --git a/lib/c/arch/arm32/linux/syscall.lst b/src/libc/arch/arm32/linux/syscall.lst diff --git a/lib/c/arch/amd64/dragonfly/time.c b/src/libc/arch/arm32/linux/time.c diff --git a/src/libc/arch/arm32/longjmp.s b/src/libc/arch/arm32/longjmp.s @@ -0,0 +1,11 @@ + .file "longjmp.s" + + .text + .globl longjmp +longjmp: + ldmia r0, {r4-r11, sp, lr} + + // If r1 is 0 return 1 instead + movs r0, r1 + moveq r0, #1 + bx lr diff --git a/src/libc/arch/arm32/setjmp.s b/src/libc/arch/arm32/setjmp.s @@ -0,0 +1,9 @@ + .file "setjmp.s" + + .text + .globl setjmp +setjmp: + // IHI0042F_aapcs.pdf 5.1.1 callee saved registers + stmia r0, {r4-r11, sp, lr} + mov r0, #0 + bx lr diff --git a/lib/c/arch/arm32/Makefile b/src/libc/arch/arm64/Makefile diff --git a/lib/c/arch/arm32/linux/.gitignore b/src/libc/arch/arm64/linux/.gitignore diff --git a/lib/c/arch/arm32/linux/Makefile b/src/libc/arch/arm64/linux/Makefile diff --git a/src/libc/arch/arm64/linux/_cerrno.s b/src/libc/arch/arm64/linux/_cerrno.s @@ -0,0 +1,13 @@ + .file "_cerrno.s" + .globl _cerrno + +_cerrno: + cmp x0,#0 + b.lt 1f + ret + +1: neg x0,x0 + adr x1,errno + str w0,[x1] + mov x0,#-1 + ret diff --git a/src/libc/arch/arm64/linux/_getheap.s b/src/libc/arch/arm64/linux/_getheap.s @@ -0,0 +1,6 @@ + .file "_getheap.s" + + .globl _getheap +_getheap: + mov x0,#0 + b _brk diff --git a/lib/c/arch/arm32/linux/_open.c b/src/libc/arch/arm64/linux/_open.c diff --git a/lib/c/arch/amd64/dragonfly/_sigaction.c b/src/libc/arch/arm64/linux/_sigaction.c diff --git a/lib/c/arch/amd64/dragonfly/_tzone.c b/src/libc/arch/arm64/linux/_tzone.c diff --git a/src/libc/arch/arm64/linux/gensys.sh b/src/libc/arch/arm64/linux/gensys.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +# +# This job is very easy because app and kernel ABI are identical +# until the 4th parameter, so we only have to set the syscall +# number in rax + +sed 's/[ ]*#.*// + /^$/d' syscall.lst | +while read num name +do +cat <<EOF > $name.s + .file "$name.s" + + .globl $name +$name: + mov x8,#$num + svc 0 + b _cerrno +EOF +done diff --git a/lib/c/arch/amd64/dragonfly/getenv.c b/src/libc/arch/arm64/linux/getenv.c diff --git a/lib/c/arch/amd64/dragonfly/raise.c b/src/libc/arch/arm64/linux/raise.c diff --git a/lib/c/arch/amd64/dragonfly/signal.c b/src/libc/arch/arm64/linux/signal.c diff --git a/src/libc/arch/arm64/linux/syscall.lst b/src/libc/arch/arm64/linux/syscall.lst @@ -0,0 +1,11 @@ +#number name +56 _openat +57 _close +63 _read +64 _write +93 _Exit +172 _getpid +129 _kill +62 _lseek +134 _sigaction +214 _brk diff --git a/lib/c/arch/amd64/dragonfly/time.c b/src/libc/arch/arm64/linux/time.c diff --git a/src/libc/arch/arm64/longjmp.s b/src/libc/arch/arm64/longjmp.s @@ -0,0 +1,22 @@ + .file "longjmp.s" + + .text + .globl longjmp +longjmp: + ldp x19, x20, [x0,#0] + ldp x21, x22, [x0,#16] + ldp x23, x24, [x0,#32] + ldp x25, x26, [x0,#48] + ldp x27, x28, [x0,#64] + ldp x29, x30, [x0,#80] + ldr x2, [x0,#104] + mov sp, x2 + ldp d8 , d9, [x0,#112] + ldp d10, d11, [x0,#128] + ldp d12, d13, [x0,#144] + ldp d14, d15, [x0,#160] + + mov x0, x1 + cbnz x1, 1f + mov x0, #1 +1: br x30 diff --git a/src/libc/arch/arm64/setjmp.s b/src/libc/arch/arm64/setjmp.s @@ -0,0 +1,20 @@ + .file "setjmp.s" + + .text + .globl setjmp +setjmp: + // IHI0055B_aapcs64.pdf 5.1.1, 5.1.2 callee saved registers + stp x19, x20, [x0,#0] + stp x21, x22, [x0,#16] + stp x23, x24, [x0,#32] + stp x25, x26, [x0,#48] + stp x27, x28, [x0,#64] + stp x29, x30, [x0,#80] + mov x2, sp + str x2, [x0,#104] + stp d8, d9, [x0,#112] + stp d10, d11, [x0,#128] + stp d12, d13, [x0,#144] + stp d14, d15, [x0,#160] + mov x0, #0 + ret diff --git a/src/libc/arch/generrno.sh b/src/libc/arch/generrno.sh @@ -0,0 +1,35 @@ +#!/bin/sh + +trap 'r=$?; rm -f $$.tmp; exit $r' EXIT HUP QUIT INT TERM + +for i +do + case $i in + -o) + out=$2 + shift 2 + ;; + --) + shift + break + ;; + -*) + echo usage: generrno.sh [-o output] file ... + exit 1 + ;; + *) + break + ;; + esac +done + +awk ' +/^E/ && $2 > 0 { + errno[$1] = $2 +} + +END { + for (i in errno) + print "#define", i, errno[i] | "sort -n -k3" + close("sort -n -k3") +}' $@ > $$.tmp && mv $$.tmp ${out:-errno.h} diff --git a/src/libc/arch/generrstr.sh b/src/libc/arch/generrstr.sh @@ -0,0 +1,23 @@ +#!/bin/sh + +trap 'r=$?; rm -f $$.tmp; exit $r' EXIT HUP INT QUIT TERM + +awk ' +/^E/ && $2 > 0 { + str = "" + for (i = 3; i <= NF; i++) + str = str " " $i + sub(/^ /, "", str) + errstr[$1] = str + if ($2 > max) + max = $2; +} + +END { + print "#include <errno.h>\n" + print "char *_sys_errlist[] = {" + for (i in errstr) + printf "\t%-20.20s = \"%s\",\n", "[" i "]", errstr[i] + print "};" + print "int _sys_nerr =", $2 + 1 ";" +}' $@ > $$.tmp && mv $$.tmp _sys_errlist.c diff --git a/src/libc/arch/mkerrstr b/src/libc/arch/mkerrstr @@ -0,0 +1,24 @@ +#!/bin/sh + +trap 'r=$?; rm -f $$.tmp; exit $r' EXIT HUP INT QUIT TERM + +awk ' +/^#define[ \t]*E/{ + str = "" + for (i = 5; i < NF; i++) + str = str " " $i + sub(/^ /, "", str) + errstr[$2] = str + if ($3 > max) + max = $3; +} + +END { + print "#include <errno.h>\n" + print "char *const _sys_errlist[] = {" + for (i in errstr) + printf "\t%-20.20s = \"%s\",\n", "[" i "]", errstr[i] + + print "};" + print "const int _sys_nerr =", max";" +}' $@ > $$.tmp && mv $$.tmp _sys_errlist.c diff --git a/src/libc/arch/posix/_tzone.c b/src/libc/arch/posix/_tzone.c @@ -0,0 +1,27 @@ +#include <stdlib.h> +#include <time.h> +#include "../../libc.h" + +struct tzone * +_tzone(struct tm *tm) +{ + static struct tzone tz; + static int first = 1; + + if (!first) + return &tz; + + tz.name = getenv("TZ"); + if (!tz.name || *tz.name == '\0') { + tz.name = NULL; + tz.gmtoff = 0; + tz.isdst = 0; + } else { + /* TODO: parse TZ string */ + tz.gmtoff = 0; + tz.isdst = 0; + } + first = 0; + + return &tz; +} diff --git a/src/libc/arch/posix/getenv.c b/src/libc/arch/posix/getenv.c @@ -0,0 +1,18 @@ +#include <stdlib.h> +#include <string.h> +#undef getenv + +extern char **_environ; + +char * +getenv(const char *name) +{ + char **p, *s; + size_t len = strlen(name); + + for (p = _environ; s = *p; ++p) { + if (!strncmp(name, s, len) && s[len] == '=') + return s + len + 1; + } + return NULL; +} diff --git a/src/libc/arch/posix/geterrno.sh b/src/libc/arch/posix/geterrno.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +awk '/define[ ]*E/ && $3 ~ /[0-9]+/ && $3 > 0 { + sub(/\#define[ ]*/, "") + sub(/\/\*/, "") + sub(/\*\//, "") + print +}' /usr/include/sys/errno.h diff --git a/src/libc/arch/posix/raise.c b/src/libc/arch/posix/raise.c @@ -0,0 +1,11 @@ +#include <stddef.h> +#include <signal.h> +#include <sys.h> + +#undef raise + +int +raise(int signum) +{ + return _kill(_getpid(), signum); +} diff --git a/src/libc/arch/posix/signal.c b/src/libc/arch/posix/signal.c @@ -0,0 +1,17 @@ +#include <stddef.h> +#include <signal.h> +#include <sys.h> +#undef signal + +void +(*signal(int signum, void (*func)(int)))(int) +{ + struct sigaction sa = { + .sa_handler = func, + }; + + if (_sigaction(signum, &sa, &sa) < 0) + return SIG_ERR; + + return sa.sa_handler; +} diff --git a/src/libc/arch/posix/time.c b/src/libc/arch/posix/time.c @@ -0,0 +1,21 @@ +#include <time.h> + +struct timeval { + time_t tv_sec; + int tv_usec; /* TODO use a arch type */ +}; + +int +_gettimeofday(struct timeval * restrict tp, void * restrict tzp); + +time_t +time(time_t *t) +{ + struct timeval tv; + + if (_gettimeofday(&tv, NULL) == -1) + return -1; + if (t) + *t =tv.tv_sec; + return tv.tv_sec; +} diff --git a/src/libc/arch/rules.mk b/src/libc/arch/rules.mk @@ -0,0 +1,6 @@ +MORECFLAGS = -w -I$(INCDIR) -I$(INCDIR)/bits/$(SYS) -I$(INCDIR)/bits/$(ARCH) + +SYSERRNO = $(INCDIR)/bits/$(SYS)/sys/errno.h + +_sys_errlist.c: $(SYSERRNO) + ../../mkerrstr $(SYSERRNO) diff --git a/src/libc/assert/Makefile b/src/libc/assert/Makefile @@ -0,0 +1,10 @@ +.POSIX: +PROJECTDIR =../../.. +include $(PROJECTDIR)/scripts/rules.mk + +MORECFLAGS = -w -I$(INCDIR) -I$(INCDIR)/bits/$(SYS) -I$(INCDIR)/bits/$(ARCH) + +OBJS = __assert.o\ + assert.o\ + +all: $(OBJS) diff --git a/src/libc/assert/__assert.c b/src/libc/assert/__assert.c @@ -0,0 +1,9 @@ +#include <assert.h> +#include <stdlib.h> +#include <stdio.h> + +void __assert(char *exp, char *file, long line) +{ + fprintf(stderr, "%s:%ld: assertion failed '%s'\n", file, line, exp); + abort(); +} diff --git a/src/libc/assert/assert.c b/src/libc/assert/assert.c @@ -0,0 +1,13 @@ +#include <assert.h> +#include <stdlib.h> +#include <stdio.h> +#undef assert + +void +assert(int exp) +{ + if (exp) + return; + fputs("assert failed\n", stderr); + abort(); +} diff --git a/src/libc/ctype/Makefile b/src/libc/ctype/Makefile @@ -0,0 +1,24 @@ +.POSIX: +PROJECTDIR =../../.. +include $(PROJECTDIR)/scripts/rules.mk + +MORECFLAGS = -w -I$(INCDIR) -I$(INCDIR)/bits/$(SYS) -I$(INCDIR)/bits/$(ARCH) + +OBJS = ctype.o\ + isalnum.o\ + isalpha.o\ + isascii.o\ + isblank.o\ + iscntrl.o\ + isdigit.o\ + isgraph.o\ + islower.o\ + isprint.o\ + ispunct.o\ + isspace.o\ + isupper.o\ + isxdigit.o\ + tolower.o\ + toupper.o\ + +all: $(OBJS) diff --git a/src/libc/ctype/ctype.c b/src/libc/ctype/ctype.c @@ -0,0 +1,22 @@ +#include <ctype.h> + +/* __ctype is shifted by one to match EOF */ +const unsigned char __ctype[257] = { + 0, /* EOF */ + _C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */ + _C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */ + _C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */ + _C,_C,_C,_C,_C,_C,_C,_C, /* 24-31 */ + _S|_SP,_P,_P,_P,_P,_P,_P,_P, /* 32-39 */ + _P,_P,_P,_P,_P,_P,_P,_P, /* 40-47 */ + _D,_D,_D,_D,_D,_D,_D,_D, /* 48-55 */ + _D,_D,_P,_P,_P,_P,_P,_P, /* 56-63 */ + _P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */ + _U,_U,_U,_U,_U,_U,_U,_U, /* 72-79 */ + _U,_U,_U,_U,_U,_U,_U,_U, /* 80-87 */ + _U,_U,_U,_P,_P,_P,_P,_P, /* 88-95 */ + _P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */ + _L,_L,_L,_L,_L,_L,_L,_L, /* 104-111 */ + _L,_L,_L,_L,_L,_L,_L,_L, /* 112-119 */ + _L,_L,_L,_P,_P,_P,_P,_C, /* 120-127 */ +}; diff --git a/src/libc/ctype/isalnum.c b/src/libc/ctype/isalnum.c @@ -0,0 +1,8 @@ +#include <ctype.h> +#undef isalnum + +int +isalnum(int c) +{ + return (__ctype+1)[c] & (_U|_L|_D); +} diff --git a/src/libc/ctype/isalpha.c b/src/libc/ctype/isalpha.c @@ -0,0 +1,8 @@ +#include <ctype.h> +#undef isalpha + +int +isalpha(int c) +{ + return (__ctype+1)[c] & (_U|_L); +} diff --git a/src/libc/ctype/isascii.c b/src/libc/ctype/isascii.c @@ -0,0 +1,8 @@ +#include <ctype.h> +#undef isascii + +int +isascii(int c) +{ + return c <= 0x7f; +} diff --git a/src/libc/ctype/isblank.c b/src/libc/ctype/isblank.c @@ -0,0 +1,7 @@ +#include <ctype.h> + +int +isblank(int c) +{ + return (c == ' ') || (c == '\t'); +} diff --git a/src/libc/ctype/iscntrl.c b/src/libc/ctype/iscntrl.c @@ -0,0 +1,8 @@ +#include <ctype.h> +#undef iscntrl + +int +iscntrl(int c) +{ + return (__ctype+1)[c] & (_C); +} diff --git a/src/libc/ctype/isdigit.c b/src/libc/ctype/isdigit.c @@ -0,0 +1,8 @@ +#include <ctype.h> +#undef isdigit + +int +isdigit(int c) +{ + return (__ctype+1)[c] & (_D); +} diff --git a/src/libc/ctype/isgraph.c b/src/libc/ctype/isgraph.c @@ -0,0 +1,8 @@ +#include <ctype.h> +#undef isgraph + +int +isgraph(int c) +{ + return (__ctype+1)[c] & (_P|_U|_L|_D); +} diff --git a/src/libc/ctype/islower.c b/src/libc/ctype/islower.c @@ -0,0 +1,8 @@ +#include <ctype.h> +#undef islower + +int +islower(int c) +{ + return (__ctype+1)[c] & _L; +} diff --git a/src/libc/ctype/isprint.c b/src/libc/ctype/isprint.c @@ -0,0 +1,8 @@ +#include <ctype.h> +#undef isprint + +int +isprint(int c) +{ + return (__ctype+1)[c] & (_P|_U|_L|_D|_SP); +} diff --git a/src/libc/ctype/ispunct.c b/src/libc/ctype/ispunct.c @@ -0,0 +1,8 @@ +#include <ctype.h> +#undef ispunct + +int +ispunct(int c) +{ + return (__ctype+1)[c] & (_P); +} diff --git a/src/libc/ctype/isspace.c b/src/libc/ctype/isspace.c @@ -0,0 +1,8 @@ +#include <ctype.h> +#undef isspace + +int +isspace(int c) +{ + return (__ctype+1)[c] & _S; +} diff --git a/src/libc/ctype/isupper.c b/src/libc/ctype/isupper.c @@ -0,0 +1,8 @@ +#include <ctype.h> +#undef isupper + +int +isupper(int c) +{ + return (__ctype+1)[c] & _U; +} diff --git a/src/libc/ctype/isxdigit.c b/src/libc/ctype/isxdigit.c @@ -0,0 +1,8 @@ +#include <ctype.h> +#undef isxdigit + +int +isxdigit(int c) +{ + return (__ctype+1)[c] & (_D|_X); +} diff --git a/src/libc/ctype/tolower.c b/src/libc/ctype/tolower.c @@ -0,0 +1,9 @@ +#define __USE_MACROS +#include <ctype.h> +#undef tolower + +int +tolower(int c) +{ + return (isupper(c)) ? c | 0x20 : c; +} diff --git a/src/libc/ctype/toupper.c b/src/libc/ctype/toupper.c @@ -0,0 +1,8 @@ +#include <ctype.h> +#undef toupper + +int +toupper(int c) +{ + return (islower(c)) ? c & ~0x20 : c; +} diff --git a/src/libc/libc.h b/src/libc/libc.h @@ -0,0 +1,42 @@ +#define SUN 0 +#define MON 1 +#define TUE 2 +#define WED 3 +#define THU 4 +#define FRI 5 +#define SAT 6 + +#define JAN 0 +#define FEB 1 +#define DEC 11 + +#define EPOCH 1970 +#define FEBDAYS(y) ((_daysyear(y) == 366) ? 29 : 28) +#define SECMIN 60 +#define SECHOUR (60 * SECMIN) /* 3600 */ +#define SECDAY (24 * SECHOUR) /* 86400 */ + +#ifdef stdin +extern FILE *_fpopen(const char * restrict fname, + const char * restrict mode, + FILE * restrict fp); +#endif + +struct tzone { + char *name; + int gmtoff; + int isdst; +}; + +struct tm; + +extern struct tzone *_tzone(struct tm *tm); +extern int _daysyear(int year); +extern int _newyear(int year); +extern void *_getheap(void); +#ifdef FILE +extern int _flsbuf(FILE *fp); +extern void _allocbuf(FILE *fp); +#endif + +extern int _daysmon[12]; diff --git a/src/libc/locale/Makefile b/src/libc/locale/Makefile @@ -0,0 +1,10 @@ +.POSIX: +PROJECTDIR =../../.. +include $(PROJECTDIR)/scripts/rules.mk + +MORECFLAGS = -w -I$(INCDIR) -I$(INCDIR)/bits/$(SYS) -I$(INCDIR)/bits/$(ARCH) + +OBJS = localeconv.o\ + setlocale.o\ + +all: $(OBJS) diff --git a/src/libc/locale/localeconv.c b/src/libc/locale/localeconv.c @@ -0,0 +1,29 @@ +#include <locale.h> +#include <limits.h> +#undef localeconv + +struct lconv * +localeconv(void) +{ + static struct lconv lc = { + .decimal_point = ".", + .thousands_sep = "", + .grouping = "", + .mon_decimal_point = "", + .mon_thousands_sep = "", + .mon_grouping = "", + .positive_sign = "", + .negative_sign = "", + .currency_symbol = "", + .int_curr_symbol = "", + .frac_digits = CHAR_MAX, + .p_cs_precedes = CHAR_MAX, + .n_cs_precedes = CHAR_MAX, + .p_sep_by_space = CHAR_MAX, + .p_sign_posn = CHAR_MAX, + .n_sep_by_space = CHAR_MAX, + .n_sign_posn = CHAR_MAX, + .int_frac_digits = CHAR_MAX, + }; + return &lc; +} diff --git a/src/libc/locale/setlocale.c b/src/libc/locale/setlocale.c @@ -0,0 +1,16 @@ +#include <locale.h> +#include <stddef.h> +#undef setlocale + +char * +setlocale(int category, const char *locale) +{ + if (category > LC_TIME || category < LC_ALL) + return NULL; + if (!locale || + locale[0] == '\0' || + locale[0] == 'C' && locale[1] == '\0') { + return "C"; + } + return NULL; +} diff --git a/src/libc/mklst b/src/libc/mklst @@ -0,0 +1,12 @@ +#!/bin/sh + +set -e +trap 'r=$?;rm -f $$.tmp;exit $r' EXIT HUP QUIT INT TERM +archive=${1?'First parameter must be the archive name'} + +if test -f $archive +then + newer="-newer $archive" +fi + +find . -name '*.o' $newer > $$.tmp && mv $$.tmp objlst diff --git a/src/libc/stdio/Makefile b/src/libc/stdio/Makefile @@ -0,0 +1,47 @@ +.POSIX: +PROJECTDIR =../../.. +include $(PROJECTDIR)/scripts/rules.mk + +MORECFLAGS = -w -I$(INCDIR) -I$(INCDIR)/bits/$(SYS) -I$(INCDIR)/bits/$(ARCH) + +OBJS = __getc.o\ + __putc.o\ + _flsbuf.o\ + _fpopen.o\ + clearerr.o\ + fclose.o\ + feof.o\ + ferror.o\ + fgetc.o\ + fgets.o\ + fopen.o\ + fprintf.o\ + fputc.o\ + fputs.o\ + fread.o\ + freopen.o\ + fseek.o\ + ftell.o\ + fwrite.o\ + getc.o\ + getchar.o\ + gets.o\ + perror.o\ + printf.o\ + putc.o\ + putchar.o\ + puts.o\ + rewind.o\ + setbuf.o\ + setvbuf.o\ + snprintf.o\ + sprintf.o\ + __iob.o\ + tmpnam.o\ + vfprintf.o\ + vsnprintf.o\ + vsprintf.o\ + vprintf.o\ + _allocbuf.o\ + +all: $(OBJS) diff --git a/src/libc/stdio/__getc.c b/src/libc/stdio/__getc.c @@ -0,0 +1,39 @@ +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include "../libc.h" +#include "../syscall.h" + +int +__getc(FILE *fp) +{ + int cnt; + + if (fp->flags & (_IOEOF | _IOERR)) + return EOF; + + if ((fp->flags & (_IOREAD | _IORW)) == 0) { + fp->flags |= _IOERR; + errno = EBADF; + return EOF; + } + + if (fp->flags & _IOSTRG) { + fp->flags |= _IOEOF; + return EOF; + } + + if (fp->buf == NULL && _allocbuf(fp)) + return EOF; + + if ((cnt = _read(fp->fd, fp->buf, fp->len)) <= 0) { + fp->flags |= (cnt == 0) ? _IOEOF : _IOERR; + return EOF; + } + + fp->flags |= _IOREAD; + fp->rp = fp->buf; + fp->wp = fp->buf + cnt; + + return *fp->rp++; +} diff --git a/src/libc/stdio/__iob.c b/src/libc/stdio/__iob.c @@ -0,0 +1,20 @@ +#include <stdio.h> + +FILE __iob[FOPEN_MAX] = { + { + .fd = 0, + .flags = _IOREAD, + }, + { + .fd = 1, + .flags = _IOWRITE | _IOLBF, + }, + { + .fd = 2, + .buf = stderr->unbuf, + .len = sizeof(stderr->unbuf), + .flags = _IOWRITE | _IONBF, + .rp = stderr->unbuf, + .wp = stderr->unbuf, + }, +}; diff --git a/src/libc/stdio/__putc.c b/src/libc/stdio/__putc.c @@ -0,0 +1,78 @@ +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include "../libc.h" + +int +fflush(FILE *fp) +{ + int err; + + if (fp) + return _flsbuf(fp); + + err = 0; + for (fp = __iob; fp < &__iob[FOPEN_MAX]; ++fp) { + if ((fp->flags & _IOWRITE) == 0 && _flsbuf(fp)) + err = EOF; + } + return err; +} + +static void +cleanup(void) +{ + fflush(NULL); +} + +int +__putc(int ch, FILE *fp) +{ + static int first = 1; + + if (fp->flags & _IOERR) + return EOF; + + if (fp->flags & _IOREAD) { + fp->flags |= _IOERR; + errno = EBADF; + return EOF; + } + + if (fp->flags & _IOSTRG) { + fp->flags |= _IOERR; + return EOF; + } + + if (fp->buf == NULL && _allocbuf(fp)) + return EOF; + + if (first) { + if (atexit(cleanup)) { + fp->flags |= _IOERR; + errno = ENOMEM; + return EOF; + } + first = 0; + } + + if (fp->flags & _IOLBF) { + if (fp->wp == fp->lp && _flsbuf(fp)) + return EOF; + *fp->wp++ = ch; + if (ch == '\n' && _flsbuf(fp)) + return EOF; + } else if (fp->flags & _IOFBF) { + if (_flsbuf(fp)) + return EOF; + *fp->wp++ = ch; + fp->rp = fp->buf + fp->len; + } else { + *fp->wp++ = ch; + if (_flsbuf(fp)) + return EOF; + } + + fp->flags |= _IOWRITE; + return ch & 0xFF; +} diff --git a/src/libc/stdio/_allocbuf.c b/src/libc/stdio/_allocbuf.c @@ -0,0 +1,21 @@ +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include "../libc.h" + +int +_allocbuf(FILE *fp) +{ + char *bp; + + if ((bp = malloc(BUFSIZ)) == NULL) { + fp->flags |= _IOERR; + errno = ENOMEM; + return EOF; + } + fp->len = BUFSIZ; + fp->rp = fp->wp = fp->buf = bp; + fp->lp = bp + BUFSIZ; + + return 0; +} diff --git a/src/libc/stdio/_flsbuf.c b/src/libc/stdio/_flsbuf.c @@ -0,0 +1,23 @@ +#include <errno.h> +#include <stdio.h> + +#include "../libc.h" +#include "../syscall.h" + +int +_flsbuf(FILE *fp) +{ + size_t cnt; + + if (fp->flags&_IOREAD) + return 0; + + cnt = fp->wp - fp->buf; + if (cnt > 0 && _write(fp->fd, fp->buf, cnt) != cnt) { + fp->flags |= _IOERR; + return EOF; + } + fp->wp = fp->buf; + + return 0; +} diff --git a/src/libc/stdio/_fpopen.c b/src/libc/stdio/_fpopen.c @@ -0,0 +1,75 @@ +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys.h> +#include "../syscall.h" +#include "../libc.h" +#undef fopen + +FILE * +_fpopen(const char * restrict fname, + const char * restrict mode, + FILE * restrict fp) +{ + int i, flags, fd, rw, bin; + + flags = rw = bin = 0; + + if (mode[0] == '\0') + goto einval; + + for (i = 1; mode[i]; ++i) { + switch (mode[i]) { + case '+': + if (rw) + goto einval; + rw = 1; + break; + case 'b': + if (bin) + goto einval; + bin = 1; + break; + default: + goto einval; + } + } + + switch (mode[0]) { + case 'a': + flags |= O_APPEND | O_CREAT; + goto wrflags; + case 'w': + flags |= O_TRUNC | O_CREAT; + wrflags: + flags |= (rw) ? O_RDWR : O_WRONLY; + break; + case 'r': + flags = (rw) ? O_RDWR : O_RDONLY; + break; + default: + einval: + errno = EINVAL; + return NULL; + } + + if ((fd = _open(fname, flags)) < 0) + return NULL; + + fp->buf = NULL; + fp->fd = fd; + + if (!bin) + fp->flags |= _IOTXT; + + if (flags & O_RDWR) + fp->flags |= _IORW; + else if (flags & O_RDONLY) + fp->flags |= _IOREAD; + else + fp->flags |= _IOWRITE; + + fp->lp = fp->rp = fp->wp = NULL; + + return fp; +} diff --git a/src/libc/stdio/clearerr.c b/src/libc/stdio/clearerr.c @@ -0,0 +1,8 @@ +#include <stdio.h> +#undef clearerr + +void +clearerr(FILE *fp) +{ + fp->flags &= ~(_IOERR | _IOEOF); +} diff --git a/src/libc/stdio/fclose.c b/src/libc/stdio/fclose.c @@ -0,0 +1,32 @@ +#include <stdlib.h> +#include <stdio.h> +#include "../syscall.h" +#undef fclose + +int +fclose(FILE *fp) +{ + int r = EOF; + + if ((fp->flags & _IOSTRG) == 0 && + fp->flags & (_IOWRITE | _IOREAD | _IORW)) { + r = 0; + if (_flsbuf(fp) == EOF) + r = EOF; + if (_close(fp->fd) < 0) + r = EOF; + } + + if (fp->flags & _IOALLOC) { + free(fp->buf); + fp->buf = NULL; + } + + fp->flags &= ~(_IOWRITE | _IOREAD | _IORW | + _IOERR | _IOEOF | + _IOALLOC | + _IOTXT | + _IOSTRG); + + return r; +} diff --git a/src/libc/stdio/feof.c b/src/libc/stdio/feof.c @@ -0,0 +1,8 @@ +#include <stdio.h> +#undef feof + +int +feof(FILE *fp) +{ + return fp->flags & _IOEOF; +} diff --git a/src/libc/stdio/ferror.c b/src/libc/stdio/ferror.c @@ -0,0 +1,8 @@ +#include <stdio.h> +#undef ferror + +int +ferror(FILE *fp) +{ + return fp->flags & _IOERR; +} diff --git a/src/libc/stdio/fgetc.c b/src/libc/stdio/fgetc.c @@ -0,0 +1,8 @@ +#include <stdio.h> +#undef fgetc + +int +fgetc(FILE *fp) +{ + return getc(fp); +} diff --git a/src/libc/stdio/fgets.c b/src/libc/stdio/fgets.c @@ -0,0 +1,19 @@ +#include <stdio.h> +#undef fgets + +char * +fgets(char *s, int n, FILE *fp) +{ + int ch = 0; + char *t = s; + + while (--n > 0 && (ch = getc(fp)) != EOF) { + if ((*t++ = ch) == '\n') + break; + } + if (ch == EOF && s == t) + return NULL; + *t = '\0'; + + return s; +} diff --git a/src/libc/stdio/fopen.c b/src/libc/stdio/fopen.c @@ -0,0 +1,23 @@ +#include <errno.h> +#include <stdio.h> + +#include "../syscall.h" +#include "../libc.h" +#undef fopen + + +FILE * +fopen(const char * restrict name, const char * restrict mode) +{ + FILE *fp; + + for (fp = __iob; fp < &__iob[FOPEN_MAX]; ++fp) { + if ((fp->flags & (_IOREAD | _IOWRITE | _IORW)) == 0) + break; + } + if (fp == &__iob[FOPEN_MAX]) { + errno = ENOMEM; + return NULL; + } + return _fpopen(name, mode, fp); +} diff --git a/src/libc/stdio/fprintf.c b/src/libc/stdio/fprintf.c @@ -0,0 +1,15 @@ +#include <stdarg.h> +#include <stdio.h> +#undef fprintf + +int +fprintf(FILE * restrict fp, const char * restrict fmt, ...) +{ + va_list va; + int cnt; + + va_start(va, fmt); + cnt = vfprintf(fp, fmt, va); + va_end(va); + return cnt; +} diff --git a/src/libc/stdio/fputc.c b/src/libc/stdio/fputc.c @@ -0,0 +1,8 @@ +#include <stdio.h> +#undef fputc + +int +fputc(int c, FILE *fp) +{ + return putc(c, fp); +} diff --git a/src/libc/stdio/fputs.c b/src/libc/stdio/fputs.c @@ -0,0 +1,12 @@ +#include <stdio.h> +#undef fputs + +int +fputs(const char * restrict bp, FILE * restrict fp) +{ + int r, ch; + + while (ch = *bp++) + r = putc(ch, fp); + return r; +} diff --git a/src/libc/stdio/fread.c b/src/libc/stdio/fread.c @@ -0,0 +1,25 @@ +#include <stdio.h> +#undef fread + +size_t +fread(void * restrict ptr, size_t size, size_t nmemb, + FILE * restrict fp) +{ + unsigned char *bp = ptr; + size_t n, i; + int c; + + if (size == 0) + return 0; + + for (n = 0; n < nmemb; n++) { + i = size; + do { + if ((c = getc(fp)) == EOF) + return n; + *bp++ = c; + } while (--i); + } + + return n; +} diff --git a/src/libc/stdio/freopen.c b/src/libc/stdio/freopen.c @@ -0,0 +1,14 @@ +#include <stdio.h> + +#include "../syscall.h" +#include "../libc.h" +#undef freopen + +FILE * +freopen(const char * restrict name, const char * restrict mode, + FILE * restrict fp) +{ + if (fclose(fp) == EOF) + return NULL; + return _fpopen(name, mode, fp); +} diff --git a/src/libc/stdio/fseek.c b/src/libc/stdio/fseek.c @@ -0,0 +1,26 @@ +#include <stdio.h> +#include "../syscall.h" +#undef fseek + +int +fseek(FILE *fp, long off, int whence) +{ + if (fp->flags & _IOERR) + return EOF; + + if ((fp->flags & _IOWRITE) && _flsbuf(fp)) + return -1; + else if (whence == SEEK_CUR && (fp->flags & _IOREAD)) + off -= fp->wp - fp->rp; + + if (_lseek(fp->fd, off, whence) < 0) { + fp->flags |= _IOERR; + return EOF; + } + + if (fp->flags & _IORW) + fp->flags &= ~(_IOREAD | _IOWRITE); + fp->flags &= ~_IOEOF; + + return 0; +} diff --git a/src/libc/stdio/ftell.c b/src/libc/stdio/ftell.c @@ -0,0 +1,27 @@ +#include <stdio.h> +#include "../syscall.h" +#undef ftell + +long +ftell(FILE *fp) +{ + long off; + unsigned char *p; + + if (fp->flags & _IOERR) + return EOF; + + if ((off = _lseek(fp->fd, 0, SEEK_CUR)) < 0) { + fp->flags |= _IOERR; + return EOF; + } + + if (fp->flags & _IOREAD) + return off - (fp->wp - fp->rp); + + if (fp->flags & _IOWRITE) { + p = (fp->flags & _IOLBF) ? fp->lp : fp->wp; + return off + (p - fp->buf); + } + return off; +} diff --git a/src/libc/stdio/fwrite.c b/src/libc/stdio/fwrite.c @@ -0,0 +1,24 @@ +#include <stdio.h> +#undef fwrite + +size_t +fwrite(const void * restrict ptr, size_t size, size_t nmemb, + FILE * restrict fp) +{ + const unsigned char *bp = ptr; + size_t n, i; + + if (size == 0) + return 0; + + for (n = 0; n < nmemb; n++) { + i = size; + do + putc(*bp++, fp); + while (--i); + if (ferror(fp)) + break; + } + + return n; +} diff --git a/src/libc/stdio/getc.c b/src/libc/stdio/getc.c @@ -0,0 +1,8 @@ +#include <stdio.h> +#undef getc + +int +getc(FILE *fp) +{ + return (fp->rp >= fp->wp) ? __getc(fp) : *fp->rp++; +} diff --git a/src/libc/stdio/getchar.c b/src/libc/stdio/getchar.c @@ -0,0 +1,8 @@ +#include <stdio.h> +#undef getchar + +int +getchar(void) +{ + return getc(stdin); +} diff --git a/src/libc/stdio/gets.c b/src/libc/stdio/gets.c @@ -0,0 +1,17 @@ +#include <stdio.h> +#undef gets + +char * +gets(char *s) +{ + int ch; + char *t = s; + + while ((ch = getc(stdin)) != EOF && ch != '\n') + *t++ = ch; + if (ch == EOF && s == t) + return NULL; + *t = '\0'; + + return s; +} diff --git a/src/libc/stdio/perror.c b/src/libc/stdio/perror.c @@ -0,0 +1,16 @@ +#include <errno.h> +#include <stdio.h> +#include <string.h> +#undef perror + +void +perror(const char *msg) +{ + if (msg && *msg) { + fputs(msg, stderr); + putc(':', stderr); + putc(' ', stderr); + } + fputs(strerror(errno), stderr); + putc('\n', stderr); +} diff --git a/src/libc/stdio/printf.c b/src/libc/stdio/printf.c @@ -0,0 +1,15 @@ +#include <stdarg.h> +#include <stdio.h> +#undef printf + +int +printf(const char * restrict fmt, ...) +{ + int cnt; + va_list va; + + va_start(va, fmt); + cnt = vfprintf(stdout, fmt, va); + va_end(va); + return cnt; +} diff --git a/src/libc/stdio/putc.c b/src/libc/stdio/putc.c @@ -0,0 +1,8 @@ +#include <stdio.h> +#undef putc + +int +putc(int ch, FILE *fp) +{ + return (fp->wp >= fp->rp) ? __putc(ch,fp) : (*fp->wp++ = ch); +} diff --git a/src/libc/stdio/putchar.c b/src/libc/stdio/putchar.c @@ -0,0 +1,8 @@ +#include <stdio.h> +#undef putchar + +int +putchar(int ch) +{ + return putc(ch, stdout); +} diff --git a/src/libc/stdio/puts.c b/src/libc/stdio/puts.c @@ -0,0 +1,12 @@ +#include <stdio.h> +#undef puts + +int +puts(const char *str) +{ + int ch; + + while (ch = *str++) + putchar(ch); + return putchar('\n'); +} diff --git a/src/libc/stdio/rewind.c b/src/libc/stdio/rewind.c @@ -0,0 +1,10 @@ +#include <stdio.h> +#undef rewind + +void +rewind(FILE *fp) +{ + fp->flags &= ~_IOERR; + fseek(fp, 0, SEEK_SET); + clearerr(fp); +} diff --git a/src/libc/stdio/setbuf.c b/src/libc/stdio/setbuf.c @@ -0,0 +1,8 @@ +#include <stdio.h> +#undef setbuf + +void +setbuf(FILE * restrict fp, char * restrict buf) +{ + setvbuf(fp, buf, (buf) ? _IOFBF : _IONBF, BUFSIZ); +} diff --git a/src/libc/stdio/setvbuf.c b/src/libc/stdio/setvbuf.c @@ -0,0 +1,48 @@ +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#undef setvbuf + +int +setvbuf(FILE * restrict fp, char * restrict buf, int mode, size_t size) +{ + int flags; + char *p; + size_t l; + + if (_flsbuf(fp) == EOF) + return EOF; + + if (buf) + p = buf, l = size; + else + p = fp->buf, l = fp->len; + + switch (mode) { + case _IONBF: + l = sizeof(fp->unbuf); + p = fp->unbuf; + case _IOLBF: + case _IOFBF: + fp->rp = fp->wp = p; + fp->lp = p + l; + break; + default: + errno = EINVAL; + return EOF; + } + + flags = fp->flags; + if (flags&_IOALLOC && (buf || mode == _IONBF)) { + free(fp->buf); + flags &= ~_IOALLOC; + } + + fp->buf = p; + fp->len = l; + flags &= ~(_IONBF | _IOLBF | _IOFBF); + flags |= mode; + fp->flags = flags; + + return 0; +} diff --git a/src/libc/stdio/snprintf.c b/src/libc/stdio/snprintf.c @@ -0,0 +1,16 @@ +#include <stdarg.h> +#include <stdio.h> +#undef snprintf + +int +snprintf(char * restrict s, size_t siz, const char * restrict fmt, ...) +{ + int r; + va_list va; + + va_start(va, fmt); + r = vsnprintf(s, siz, fmt, va); + va_end(va); + + return r; +} diff --git a/src/libc/stdio/sprintf.c b/src/libc/stdio/sprintf.c @@ -0,0 +1,16 @@ +#include <stdarg.h> +#include <stdio.h> +#undef sprintf + +int +sprintf(char * restrict s, const char * restrict fmt, ...) +{ + int r; + + va_list va; + va_start(va, fmt); + r = vsprintf(s, fmt, va); + va_end(va); + + return r; +} diff --git a/src/libc/stdio/tmpnam.c b/src/libc/stdio/tmpnam.c @@ -0,0 +1,31 @@ +#include <stdio.h> +#include <string.h> +#include "../syscall.h" +#undef tmpnam + +char * +tmpnam(char *s) +{ + static char *tmpl, buf[L_tmpnam]; + char *p; + + if (*buf == '\0') { + for (tmpl = buf, p = _TMPNAME; *tmpl++ = *p++; ) + ; + for (p = tmpl; p < &buf[L_tmpnam-1]; ++p) + *p = '0'; + *p = '\0'; + } + for (;;) { + for (p = tmpl; *p && *p != '9'; ++p) + ; + if (*p == '\0') + return NULL; + ++*p; + if (_access(buf, 0) != 0) + break; + } + if (s) + strcpy(s, buf); + return buf; +} diff --git a/src/libc/stdio/vfprintf.c b/src/libc/stdio/vfprintf.c @@ -0,0 +1,362 @@ +#include <ctype.h> +#include <limits.h> +#include <stdarg.h> +#include <stdint.h> +#include <stdio.h> +#include <string.h> +#include <wchar.h> +#undef vfprintf + +enum { + LONG = 1 << 0, + LLONG = 1 << 1, + SHORT = 1 << 2, + CHAR = 1 << 3, + SIZET = 1 << 4, + PTRDIFF = 1 << 5, + INTMAX = 1 << 6, + VOIDPTR = 1 << 7, + UNSIGNED = 1 << 8, + ALTFORM = 1 << 9, +}; + +#define MAXPREC 50 + +struct conv { + int sign; + int prec; + char *digs; + int base; +}; + +static uintmax_t +getnum(va_list *va, int flags, int *sign) +{ + uintmax_t uval; + intmax_t val; + + if (flags & CHAR) { + val = va_arg(*va, int); + uval = (unsigned char) val; + } else if (flags & SHORT) { + val = va_arg(*va, int); + uval = (unsigned short) val; + } else if (flags & LONG) { + val = va_arg(*va, long); + uval = (unsigned long) val; + } else if (flags & LLONG) { + val = va_arg(*va, long long); + uval = (unsigned long long) val; + } else if (flags & SIZET) { + uval = va_arg(*va, size_t); + } else if (flags & INTMAX) { + val = va_arg(*va, intmax_t); + uval = (uintmax_t) val; + } else if (flags & VOIDPTR) { + uval = (uintmax_t) va_arg(*va, void *); + } else { + val = va_arg(*va, int); + uval = (unsigned) val; + } + + if ((flags & UNSIGNED) == 0 && val < 0) { + *sign = '-'; + uval = -uval; + } + return uval; +} + +static char * +numtostr(uintmax_t val, int flags, struct conv *conv, char *buf) +{ + char *buf0 = buf; + int base = conv->base, prec = conv->prec; + uintmax_t oval = val; + + if (prec == -1) + prec = 1; + + for (*buf = '\0'; val > 0; val /= base) + *--buf = conv->digs[val % base]; + while (buf0 - buf < prec) + *--buf = '0'; + + if (flags & ALTFORM) { + if (base == 8 && *buf != '0') { + *--buf = '0'; + } else if (base == 16 && oval != 0) { + *--buf = conv->digs[16]; + *--buf = '0'; + } + } + if (conv->sign) + *--buf = conv->sign; + + return buf; +} + +static void +savecnt(va_list *va, int flags, int cnt) +{ + if (flags & CHAR) + *va_arg(*va, char*) = cnt; + else if (flags & SHORT) + *va_arg(*va, short*) = cnt; + else if (flags & LONG) + *va_arg(*va, long*) = cnt; + else if (flags & LLONG) + *va_arg(*va, long long*) = cnt; + else if (flags & SIZET) + *va_arg(*va, size_t*) = cnt; + else if (flags & INTMAX) + *va_arg(*va, intmax_t*) = cnt; + else + *va_arg(*va, int*) = cnt; +} + +static size_t +wstrout(wchar_t *ws, size_t len, int width, int fill, FILE * restrict fp) +{ + int left = 0, adjust; + size_t cnt = 0; + wchar_t wc; +#if 0 + + if (width < 0) { + left = 1; + width = -width; + } + + len *= sizeof(wchar_t); + adjust = (len < width) ? width - len : 0; + cnt = adjust + len; + if (left) + adjust = -adjust; + + for ( ; adjust > 0; adjust++) + putc(fill, fp); + + while (wc = *ws++) + putwc(wc, fp); + + for ( ; adjust < 0; adjust--) + putc(' ', fp); +#endif + return cnt; +} + +static size_t +strout(char *s, size_t len, int width, int fill, FILE * restrict fp) +{ + int left = 0, adjust, ch, prefix; + size_t cnt = 0; + + if (width < 0) { + left = 1; + width = -width; + } + + adjust = (len < width) ? width - len : 0; + cnt = adjust + len; + if (left) + adjust = -adjust; + + if (fill == '0') { + if (*s == '-' || *s == '+') + prefix = 1; + else if (*s == '0' && toupper(s[1]) == 'X') + prefix = 2; + else + prefix = 0; + while (prefix--) { + putc(*s++, fp); + --len; + } + } + + for ( ; adjust > 0; adjust--) + putc(fill, fp); + + while (ch = *s++) + putc(ch, fp); + + for ( ; adjust < 0; adjust++) + putc(' ', fp); + + return cnt; +} + +int +vfprintf(FILE * restrict fp, const char *fmt, va_list va) +{ + int ch, n, flags, width, left, fill, cnt = 0; + size_t inc, len; + char *s; + wchar_t *ws; + struct conv conv; + char buf[MAXPREC+1]; + wchar_t wbuf[2]; + va_list va2; + + va_copy(va2, va); + for (cnt = 0; ch = *fmt++; cnt += inc) { + if (ch != '%') { + putc(ch, fp); + inc = 1; + continue; + } + + fill = ' '; + left = flags = width = 0; + conv.prec = -1; + conv.base = 10; + conv.sign = '\0'; + conv.digs = "0123456789ABCDEFX"; + +flags: + switch (*fmt++) { + case ' ': + if (conv.sign == '\0') + conv.sign = ' '; + goto flags; + case '+': + conv.sign = '+'; + goto flags; + case '#': + flags |= ALTFORM; + goto flags; + case '.': + if (*fmt == '*') { + fmt++; + n = va_arg(va2, int); + } else { + for (n = 0; isdigit(ch = *fmt); fmt++) + n = n * 10 + ch - '0'; + } + if (n > MAXPREC) + n = MAXPREC; + if (n > 0) + conv.prec = n; + goto flags; + case '*': + width = va_arg(va2, int); + goto flags; + case '-': + left = 1; + ++fmt; + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + --fmt; + for (n = 0; isdigit(ch = *fmt); ++fmt) + n = n * 10 + ch - '0'; + if (left) + n = -n; + width = n; + goto flags; + case '0': + fill = '0'; + goto flags; + case 'l': + flags += LONG; + goto flags; + case 'h': + flags += SHORT; + goto flags; + case '%': + ch = '%'; + goto cout; + case 'c': + if (flags & LONG) { + wbuf[0] = va_arg(va2, wint_t); + wbuf[1] = L'\0'; + ws = wbuf; + len = 1; + goto wstrout; + } + ch = va_arg(va2, int); + cout: + buf[0] = ch; + buf[1] = '\0'; + s = buf; + len = 1; + goto strout; + case 'j': + flags |= INTMAX; + goto flags; + case 't': + flags |= PTRDIFF; + goto flags; + case 'z': + flags |= SIZET; + goto flags; + case 'u': + flags |= UNSIGNED; + case 'i': + case 'd': + conv.base = 10; + goto numeric; + case 'p': + flags |= VOIDPTR | ALTFORM; + goto numeric16; + case 'x': + conv.digs = "0123456789abcdefx"; + case 'X': + numeric16: + conv.base = 16; + flags |= UNSIGNED; + goto numeric; + case 'o': + conv.base = 8; + flags |= UNSIGNED; + numeric: + if (conv.prec != -1) + fill = ' '; + s = numtostr(getnum(&va2, flags, &conv.sign), + flags, + &conv, + &buf[MAXPREC]); + len = &buf[MAXPREC] - s; + goto strout; + case 'L': + case 'a': + case 'A': + case 'e': + case 'E': + case 'f': + case 'g': + case 'G': + /* TODO */ + case 's': + if (flags & LONG) { + ws = va_arg(va2, wchar_t *); + /* len = wcsnlen(ws, conv.prec); */ + goto wstrout; + } else { + s = va_arg(va2, char *); + len = strnlen(s, conv.prec); + goto strout; + } + wstrout: + inc = wstrout(ws, len, width, fill, fp); + break; + strout: + inc = strout(s, len, width, fill, fp); + break; + case 'n': + savecnt(&va2, flags, cnt); + break; + case '\0': + goto out_loop; + } + } + +out_loop: + return (ferror(fp)) ? EOF : cnt; +} diff --git a/src/libc/stdio/vprintf.c b/src/libc/stdio/vprintf.c @@ -0,0 +1,12 @@ +#include <stdarg.h> +#include <stdio.h> +#undef vprintf + +int +vprintf(const char *fmt, va_list ap) +{ + va_list ap2; + + va_copy(ap2, ap); + return vfprintf(stdout, fmt, ap2); +} diff --git a/src/libc/stdio/vsnprintf.c b/src/libc/stdio/vsnprintf.c @@ -0,0 +1,25 @@ +#include <stdarg.h> +#include <stdio.h> +#undef vsnprintf + +int +vsnprintf(char * restrict s, size_t siz, const char * restrict fmt, va_list ap) +{ + FILE f; + int r; + + f.flags = _IORW | _IOSTRG; + f.len = siz; + f.buf = s; + f.wp = s; + f.rp = s + siz; + + r = vfprintf(&f, fmt, ap); + if (s) { + if (f.wp == f.rp) + --f.wp; + *f.wp = '\0'; + } + + return r; +} diff --git a/src/libc/stdio/vsprintf.c b/src/libc/stdio/vsprintf.c @@ -0,0 +1,12 @@ +#include <limits.h> +#include <stdarg.h> +#include <stdint.h> +#include <stdio.h> +#undef vsprintf + + +int +vsprintf(char * restrict s, const char * restrict fmt, va_list va) +{ + return vsnprintf(s, SIZE_MAX, fmt, va); +} diff --git a/src/libc/stdlib/Makefile b/src/libc/stdlib/Makefile @@ -0,0 +1,25 @@ +.POSIX: +PROJECTDIR =../../.. +include $(PROJECTDIR)/scripts/rules.mk + +MORECFLAGS = -w -I$(INCDIR) -I$(INCDIR)/bits/$(SYS) -I$(INCDIR)/bits/$(ARCH) + +OBJS = abort.o\ + abs.o\ + atexit.o\ + atoi.o\ + atol.o\ + atoll.o\ + bsearch.o\ + calloc.o\ + errno.o\ + exit.o\ + labs.o\ + llabs.o\ + malloc.o\ + qsort.o\ + rand.o\ + realloc.o\ + strtoull.o\ + +all: $(OBJS) diff --git a/src/libc/stdlib/abort.c b/src/libc/stdlib/abort.c @@ -0,0 +1,10 @@ +#include <signal.h> +#include <stdlib.h> +#undef abort + +void +abort(void) +{ + raise(SIGABRT); + _Exit(127); +} diff --git a/src/libc/stdlib/abs.c b/src/libc/stdlib/abs.c @@ -0,0 +1,8 @@ +#include <stdlib.h> +#undef abs + +int +abs(int n) +{ + return (n < 0) ? -n : n; +} diff --git a/src/libc/stdlib/atexit.c b/src/libc/stdlib/atexit.c @@ -0,0 +1,17 @@ +#include <stdlib.h> +#include <errno.h> +#undef atexit + +extern void (*_exitf[_ATEXIT_MAX])(void); +extern unsigned _exitn; + +int +atexit(void (*fun)(void)) +{ + if (_exitn == _ATEXIT_MAX) { + errno = ENOMEM; + return -1; + } + _exitf[_exitn++] = fun; + return 0; +} diff --git a/src/libc/stdlib/atoi.c b/src/libc/stdlib/atoi.c @@ -0,0 +1,25 @@ +#include <ctype.h> +#include <stdlib.h> +#undef atoi + +int +atoi(const char *s) +{ + int n, sign = -1; + + while (isspace(*s)) + ++s; + + switch (*s) { + case '-': + sign = 1; + case '+': + ++s; + } + + /* Compute n as a negative number to avoid overflow on INT_MIN */ + for (n = 0; isdigit(*s); ++s) + n = 10*n - (*s - '0'); + + return sign * n; +} diff --git a/src/libc/stdlib/atol.c b/src/libc/stdlib/atol.c @@ -0,0 +1,26 @@ +#include <ctype.h> +#include <stdlib.h> +#undef atol + +long +atol(const char *s) +{ + int sign = -1; + long n; + + while (isspace(*s)) + ++s; + + switch (*s) { + case '-': + sign = 1; + case '+': + ++s; + } + + /* Compute n as a negative number to avoid overflow on LONG_MIN */ + for (n = 0; isdigit(*s); ++s) + n = 10*n - (*s - '0'); + + return sign * n; +} diff --git a/src/libc/stdlib/atoll.c b/src/libc/stdlib/atoll.c @@ -0,0 +1,26 @@ +#include <ctype.h> +#include <stdlib.h> +#undef atoll + +long long +atoll(const char *s) +{ + int sign = -1; + long long n; + + while (isspace(*s)) + ++s; + + switch (*s) { + case '-': + sign = 1; + case '+': + ++s; + } + + /* Compute n as a negative number to avoid overflow on LLONG_MIN */ + for (n = 0; isdigit(*s); ++s) + n = 10*n - (*s - '0'); + + return sign * n; +} diff --git a/src/libc/stdlib/bsearch.c b/src/libc/stdlib/bsearch.c @@ -0,0 +1,26 @@ +#include <stdlib.h> + +void * +bsearch(const void *key, const void *ary, size_t n, size_t size, + int (*cmp)(const void *, const void *)) +{ + int t; + size_t mid, low, high; + char *cur, *base = ary; + + low = 0; + high = n - 1; + while (low <= high) { + mid = low + (high - low) / 2; + cur = base + mid*size; + + if ((t = (*cmp)(key, cur)) == 0) + return cur; + else if (t > 0) + low = mid + 1; + else + high = mid - 1; + } + + return NULL; +} diff --git a/src/libc/stdlib/calloc.c b/src/libc/stdlib/calloc.c @@ -0,0 +1,18 @@ +#include <stdlib.h> +#include <string.h> +#undef calloc + +void * +calloc(size_t nmemb, size_t size) +{ + size_t nbytes; + void *mem; + + if (!nmemb || !size || nmemb > (size_t)-1/size) + return NULL; + + nbytes = nmemb * size; + if ((mem = malloc(nbytes)) == NULL) + return NULL; + return memset(mem, 0, nbytes); +} diff --git a/src/libc/stdlib/errno.c b/src/libc/stdlib/errno.c @@ -0,0 +1 @@ +int errno; diff --git a/src/libc/stdlib/exit.c b/src/libc/stdlib/exit.c @@ -0,0 +1,13 @@ +#include <stdlib.h> +#undef exit + +void (*_exitf[_ATEXIT_MAX])(void); +unsigned _exitn; + +void +exit(int status) +{ + while (_exitn > 0) + (*_exitf[--_exitn])(); + _Exit(status); +} diff --git a/src/libc/stdlib/labs.c b/src/libc/stdlib/labs.c @@ -0,0 +1,8 @@ +#include <stdlib.h> +#undef labs + +long +labs(long n) +{ + return (n < 0) ? -n : n; +} diff --git a/src/libc/stdlib/llabs.c b/src/libc/stdlib/llabs.c @@ -0,0 +1,8 @@ +#include <stdlib.h> +#undef llabs + +long long +llabs(long long n) +{ + return (n < 0) ? -n : n; +} diff --git a/src/libc/stdlib/malloc.c b/src/libc/stdlib/malloc.c @@ -0,0 +1,158 @@ +#include <errno.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> + +#include "malloc.h" +#include "../syscall.h" + +#define MAXADDR ((char *)-1) +#define ERRADDR ((char *)-1) + +static Header base = { .h.next = &base }; +static Header *freep = &base; + +/* + * Run over the free list looking for the nearest previous + * block. There are two possible results: end of the list + * or an intermediary block. + */ +void * +_prevchunk(Header *hp) +{ + Header *p; + + for (p = freep; ;p = p->h.next) { + /* hp between p and p->h.next? */ + if (p < hp && hp < p->h.next) + break; + /* p before hp and hp at the end of list? */ + if (p->h.next <= p && (hp < p->h.next || hp > p)) + break; + } + return p; +} + +/* + * Get the previous block and try to merge + * with next and previous blocks + */ +void +free(void *mem) +{ + Header *hp, *prev; + + if (!mem) + return; + + hp = (Header *) mem - 1; + prev = _prevchunk(hp); + + /* join to next */ + if (hp + hp->h.size == prev->h.next) { + hp->h.size += prev->h.next->h.size; + hp->h.next = prev->h.next->h.next; + } else { + hp->h.next = prev->h.next; + } + + /* join to previous */ + if (prev + prev->h.size == hp) { + prev->h.size += hp->h.size; + prev->h.next = hp->h.next; + } else { + prev->h.next = hp; + } + + freep = prev; +} + +static void * +sbrk(uintptr_t inc) +{ + char *new, *old; + void *p; + static void *heap; + + if (!heap) + heap = _getheap(); + old = heap; + if (old >= MAXADDR - inc) + return ERRADDR; + new = old + inc; + p = _brk(new); + if (p == old || p < 0) + return ERRADDR; + heap = new; + + return old; +} + +static Header * +morecore(size_t nunits) +{ + char *rawmem; + Header *hp; + + if (nunits < NALLOC) + nunits = NALLOC; + + rawmem = sbrk(nunits * sizeof(Header)); + if (rawmem == ERRADDR) + return NULL; + + hp = (Header*)rawmem; + hp->h.size = nunits; + + /* integrate new memory into the list */ + free(hp + 1); + + return freep; +} + +/* + * Run over the list of free blocks trying to find a block + * big enough for nbytes. If the block fit perfectly with + * the required size then we only have to unlink + * the block. Otherwise we have to split the block and + * return the right part. If we run over the full list + * without a fit then we have to require more memory + * + * ______________________________________ + * ___________./______________________________________\_____ + * ...| in | | | in | |.....| in | | | |.... + * ...| use | | | use | |.....| use | | | |.... + * ___|______|___|.____|_____|._|_____|______|._|.___|.|____ + * \__/ \_________/ \_____________/ \/ \__/ + */ +void * +malloc(size_t nbytes) +{ + Header *cur, *prev; + size_t nunits; + + /* 1 unit for header plus enough units to fit nbytes */ + nunits = (nbytes+sizeof(Header)-1) / sizeof(Header) + 1; + + for (prev = freep; ; prev = cur) { + cur = prev->h.next; + if (cur->h.size >= nunits) { + if (cur->h.size == nunits) { + prev->h.next = cur->h.next; + } else { + cur->h.size -= nunits; + cur += cur->h.size; + cur->h.size = nunits; + } + freep = prev; + return cur + 1; + } + + if (cur == freep) { + if ((cur = morecore(nunits)) == NULL) { + errno = ENOMEM; + return NULL; + } + } + } +} diff --git a/src/libc/stdlib/malloc.h b/src/libc/stdlib/malloc.h @@ -0,0 +1,16 @@ +#include <stdlib.h> + +/* minimum amount of required units */ +#define NALLOC 10000 + +typedef union header Header; +union header { + struct hdr { + Header *next; + size_t size; + } h; + /* most restrictive type fixes the union size for alignment */ + _ALIGNTYPE most; +}; + +extern void *_prevchunk(Header *hp); diff --git a/src/libc/stdlib/qsort.c b/src/libc/stdlib/qsort.c @@ -0,0 +1,68 @@ +#include <stdlib.h> +#include <string.h> +#undef qsort + +/* + * This implementation of qsort is based in the paper + * "Engineering a Sort Function", by Jon L.Bentley and M. Douglas McIlroy. + * A lot of different optimizations were removed to make the code simpler. + */ + +struct qsort { + size_t es; + int (*cmp)(const void *, const void *); +}; + +static void +swap(char *i, char *j, size_t n) +{ + do { + char c = *i; + *i++ = *j; + *j++ = c; + } while (--n > 0); +} + +static void +xqsort(char *a, size_t n, struct qsort *qs) +{ + size_t j, es = qs->es; + char *pi, *pj, *pn; + + if (n <= 1) + return; + + pi = a; + pn = pj = a + n*es; + + swap(a, a + n/2 * es, es); + for (;;) { + do { + pi += es; + } while (pi < pn && qs->cmp(pi, a) < 0); + + do { + pj -= es; + } while (pj > a && qs->cmp(pj, a) > 0); + + if (pj < pi) + break; + swap(pi, pj, es); + } + swap(a, pj, es); + + j = (pj - a) / es; + xqsort(a, j, qs); + xqsort(a + (j+1)*es, n-j-1, qs); +} + +void +qsort(void *base, size_t nmemb, size_t size, + int (*f)(const void *, const void *)) +{ + struct qsort qs; + + qs.cmp = f; + qs.es = size; + xqsort(base, nmemb, &qs); +} diff --git a/src/libc/stdlib/rand.c b/src/libc/stdlib/rand.c @@ -0,0 +1,18 @@ +#include <stdlib.h> +#undef rand +#undef srand + +static unsigned long next; + +void +srand(unsigned seed) +{ + next = seed; +} + +int +rand(void) /* RAND_MAX assumed to be 32767. */ +{ + next = next * 1103515245 + 12345; + return (unsigned)(next/65536) % 32768; +} diff --git a/src/libc/stdlib/realloc.c b/src/libc/stdlib/realloc.c @@ -0,0 +1,68 @@ +#include <stdlib.h> +#include <string.h> + +#include "malloc.h" +#undef realloc + +void * +realloc(void *ptr, size_t nbytes) +{ + Header *oh, *prev, *next, *new; + size_t nunits, avail, onbytes, n; + + if (!nbytes) + return NULL; + + if (!ptr) + return malloc(nbytes); + + nunits = (nbytes + sizeof(Header) - 1) / sizeof(Header) + 1; + oh = (Header*)ptr - 1; + + if (oh->h.size == nunits) + return ptr; + + new = oh + nunits; + + if (nunits < oh->h.size - 1) { + new->h.size = oh->h.size - nunits; + oh->h.size = nunits; + free(new + 1); + return oh; + } + + prev = _prevchunk(oh); + + if (oh + oh->h.size == prev->h.next) { + /* + * if there is free space adjacent + * to the current memory + */ + next = prev->h.next; + avail = oh->h.size + next->h.size; + + if (avail == nunits) { + oh->h.size = nunits; + prev->h.next = next->h.next; + return oh; + } + + if (avail > nunits) { + oh->h.size = nunits; + prev->h.next = new; + new->h.next = next; + new->h.size = avail - nunits; + return oh; + } + } + + onbytes = (oh->h.size - 1) * sizeof(Header); + if ((new = malloc(nbytes)) == NULL) + return NULL; + + n = (onbytes > nbytes) ? nbytes : onbytes; + memcpy(new, ptr, n); + free(ptr); + + return new; +} diff --git a/src/libc/stdlib/strtoull.c b/src/libc/stdlib/strtoull.c @@ -0,0 +1,64 @@ +#include <ctype.h> +#include <errno.h> +#include <limits.h> +#include <stdlib.h> +#include <string.h> + +#undef strtoull + +unsigned long long +strtoull(const char *s, char **end, int base) +{ + int d, sign = 1; + unsigned long long n; + static const char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + const char *t, *p; + + while (isspace(*s)) + ++s; + + switch (*s) { + case '-': + sign = -1; + case '+': + ++s; + } + + if (base == 0) { + if (*s == '0' && toupper(s[1]) == 'X') + base = 16; + else if (*s == '0') + base = 8; + else + base = 10; + } + + if (base == 16 && *s == '0' && toupper(s[1]) == 'X') + s += 2; + + n = 0; + for (t = s; p = strchr(digits, toupper(*t)); ++t) { + if ((d = p - digits) >= base) + break; + if (n > ULLONG_MAX/base) + goto overflow; + n *= base; + if (d > ULLONG_MAX - n) + goto overflow; + n += d; + } + + + if (end) + *end = t; + if (n == 0 && s == t) + errno = EINVAL; + return n*sign; + +overflow: + if (end) + *end = t; + errno = ERANGE; + + return ULLONG_MAX; +} diff --git a/src/libc/string/Makefile b/src/libc/string/Makefile @@ -0,0 +1,31 @@ +.POSIX: +PROJECTDIR =../../.. +include $(PROJECTDIR)/scripts/rules.mk + +MORECFLAGS = -w -I$(INCDIR) -I$(INCDIR)/bits/$(SYS) -I$(INCDIR)/bits/$(ARCH) + +OBJS = memchr.o\ + memcmp.o\ + memcpy.o\ + memmove.o\ + memset.o\ + strcat.o\ + strchr.o\ + strcmp.o\ + strcoll.o\ + strcpy.o\ + strcspn.o\ + strerror.o\ + strlen.o\ + strncat.o\ + strncmp.o\ + strncpy.o\ + strnlen.o\ + strpbrk.o\ + strrchr.o\ + strspn.o\ + strstr.o\ + strtok.o\ + strxfrm.o\ + +all: $(OBJS) diff --git a/src/libc/string/memchr.c b/src/libc/string/memchr.c @@ -0,0 +1,12 @@ +#include <string.h> +#undef memchr + +void * +memchr(const void *s, int c, size_t n) +{ + const unsigned char *bp = s; + + while (n > 0 && *bp++ != c) + --n; + return (n == 0) ? NULL : bp-1; +} diff --git a/src/libc/string/memcmp.c b/src/libc/string/memcmp.c @@ -0,0 +1,14 @@ +#include <string.h> +#undef memcmp + +int +memcmp(const void *s1, const void *s2, size_t n) +{ + const char *s = s1; + const char *t = s2; + + for ( ; n > 0 && *s == *t; --n) + ++s, ++t; + + return (n > 0) ? *(unsigned char *) s - *(unsigned char *) t : 0; +} diff --git a/src/libc/string/memcpy.c b/src/libc/string/memcpy.c @@ -0,0 +1,13 @@ +#include <string.h> +#undef memcpy + +void * +memcpy(void * restrict dst, const void * restrict src, size_t n) +{ + char *s1 = dst; + const char *s2 = src; + + while (n-- > 0) + *s1++ = *s2++; + return dst; +} diff --git a/src/libc/string/memmove.c b/src/libc/string/memmove.c @@ -0,0 +1,18 @@ +#include <string.h> +#undef memmove + +void * +memmove(void *dst, const void *src, size_t n) +{ + char *d = dst, *s = (char *) src; + + if (d < s) { + while (n-- > 0) + *d++ = *s++; + } else { + s += n-1, d += n-1; + while (n-- > 0) + *d-- = *s--; + } + return dst; +} diff --git a/src/libc/string/memset.c b/src/libc/string/memset.c @@ -0,0 +1,12 @@ +#include <string.h> +#undef memset + +void * +memset(void *s, int c, size_t n) +{ + char *m = s; + + while (n-- > 0) + *m++ = c; + return s; +} diff --git a/src/libc/string/strcat.c b/src/libc/string/strcat.c @@ -0,0 +1,14 @@ +#include <string.h> +#undef strcat + +char * +strcat(char * restrict dst, const char * restrict src) +{ + char *ret = dst; + + while (*dst) + ++dst; + while (*dst++ = *src++) + ; + return ret; +} diff --git a/src/libc/string/strchr.c b/src/libc/string/strchr.c @@ -0,0 +1,10 @@ +#include <string.h> +#undef strchr + +char * +strchr(const char *s, int c) +{ + while (*s && *s != c) + ++s; + return (*s == c) ? (char *)s : NULL; +} diff --git a/src/libc/string/strcmp.c b/src/libc/string/strcmp.c @@ -0,0 +1,10 @@ +#include <string.h> +#undef strcmp + +int +strcmp(const char *s1, const char *s2) +{ + while (*s1 && *s2 && *s1 == *s2) + ++s1, ++s2; + return *(unsigned char *)s1 - *(unsigned char *)s2; +} diff --git a/src/libc/string/strcoll.c b/src/libc/string/strcoll.c @@ -0,0 +1,10 @@ +#include <string.h> +#undef strcoll + +int +strcoll(const char *s1, const char *s2) +{ + while (*s1 && *s2 && *s1 == *s2) + ++s1, ++s2; + return *(unsigned char *) s1 - *(unsigned char *) s2; +} diff --git a/src/libc/string/strcpy.c b/src/libc/string/strcpy.c @@ -0,0 +1,12 @@ +#include <string.h> +#undef strcpy + +char * +strcpy(char * restrict dst, const char * restrict src) +{ + char *ret = dst; + + while (*dst++ = *src++) + ; + return ret; +} diff --git a/src/libc/string/strcspn.c b/src/libc/string/strcspn.c @@ -0,0 +1,21 @@ +#include <string.h> +#undef strcspn + +size_t +strcspn(const char *s1, const char *s2) +{ + const unsigned char *s = s1; + const unsigned char *accept = s2; + unsigned ch; + size_t n; + char buf[__NUMCHARS]; + + memset(buf, 0, sizeof(buf)); + while (ch = *accept++) + buf[ch] = 1; + + for (n = 0; (ch = *s++) && !buf[ch]; ++n) + ; + + return n; +} diff --git a/src/libc/string/strerror.c b/src/libc/string/strerror.c @@ -0,0 +1,11 @@ +#include <errno.h> +#include <string.h> +#undef strerror + +char * +strerror(int errnum) +{ + if (errnum > _sys_nerr) + errnum = EUNKNOWN; + return _sys_errlist[errnum]; +} diff --git a/src/libc/string/strlen.c b/src/libc/string/strlen.c @@ -0,0 +1,12 @@ +#include <string.h> +#undef strlen + +size_t +strlen(const char *s) +{ + const char *t; + + for (t = s; *t; ++t) + ; + return t - s; +} diff --git a/src/libc/string/strncat.c b/src/libc/string/strncat.c @@ -0,0 +1,15 @@ +#include <string.h> +#undef strncat + +char * +strncat(char * restrict dst, const char * restrict src, size_t n) +{ + char *ret = dst; + + while (*dst) + ++dst; + while (n-- > 0 && *src) + *dst++ = *src++; + *dst = '\0'; + return ret; +} diff --git a/src/libc/string/strncmp.c b/src/libc/string/strncmp.c @@ -0,0 +1,14 @@ +#include <string.h> +#undef strncmp + +int +strncmp(const char *s1, const char *s2, size_t n) +{ + int c; + + for ( ; n > 0 && (c = *s1) && c == *s2; --n) + ++s1, ++s2; + if (n == 0) + return 0; + return *(unsigned char *) s1 - *(unsigned char *) s2; +} diff --git a/src/libc/string/strncpy.c b/src/libc/string/strncpy.c @@ -0,0 +1,14 @@ +#include <string.h> +#undef strncpy + +char * +strncpy(char * restrict dst, const char * restrict src, size_t n) +{ + char *ret = dst; + + for (; n > 0 && *src; --n) + *dst++ = *src++; + while (n-- > 0) + *dst++ = '\0'; + return ret; +} diff --git a/src/libc/string/strnlen.c b/src/libc/string/strnlen.c @@ -0,0 +1,13 @@ +#include <string.h> + +#undef strnlen + +size_t +strnlen(const char *s, size_t maxlen) +{ + size_t n; + + for (n = 0; n < maxlen && *s++; ++n) + ; + return n; +} diff --git a/src/libc/string/strpbrk.c b/src/libc/string/strpbrk.c @@ -0,0 +1,20 @@ +#include <string.h> +#undef strpbrk + +char * +strpbrk(const char *s1, const char *s2) +{ + const unsigned char *s = s1; + const unsigned char *accept = s2; + unsigned ch; + char buf[__NUMCHARS]; + + memset(buf, 0, sizeof(buf)); + while (ch = *accept++) + buf[ch] = 1; + + while ((ch = *s) && !buf[ch]) + s++; + + return (ch == '\0') ? NULL : (char *) s; +} diff --git a/src/libc/string/strrchr.c b/src/libc/string/strrchr.c @@ -0,0 +1,14 @@ +#include <string.h> +#undef strrchr + +char * +strrchr(const char *s, int c) +{ + const char *t = s; + + while (*t) + ++t; + while (t > s && *t != c) + --t; + return (*t == c) ? (char *)t : NULL; +} diff --git a/src/libc/string/strspn.c b/src/libc/string/strspn.c @@ -0,0 +1,21 @@ +#include <string.h> +#undef strspn + +size_t +strspn(const char *s1, const char *s2) +{ + const unsigned char *s = s1; + const unsigned char *accept = s2; + unsigned ch; + size_t n; + char buf[__NUMCHARS]; + + memset(buf, 0, sizeof(buf)); + while (ch = *accept++) + buf[ch] = 1; + + for (n = 0; (ch = *s++) && buf[ch]; ++n) + ; + + return n; +} diff --git a/src/libc/string/strstr.c b/src/libc/string/strstr.c @@ -0,0 +1,18 @@ +#include <stddef.h> +#include <string.h> +#undef strstr + +char * +strstr(const char *s1, const char *s2) +{ + const char *p; + int c = *s2; + + if (c == '\0') + return NULL; + for (p = s1; p = strchr(p, c); ++p) { + if (!strcmp(p, s2)) + return (char *) p; + } + return NULL; +} diff --git a/src/libc/string/strtok.c b/src/libc/string/strtok.c @@ -0,0 +1,25 @@ +#include <string.h> +#undef strtok + +char * +strtok(char * restrict s, const char * restrict delim) +{ + static char *line; + + if (s) + line = s; + if (!s && !line) + return NULL; + + s = line + strspn(line, delim); + if (*s == '\0') + return line = NULL; + + line = s + strcspn(s, delim); + if (*line != '\0') + *line++ = '\0'; + else + line = NULL; + + return s; +} diff --git a/src/libc/string/strxfrm.c b/src/libc/string/strxfrm.c @@ -0,0 +1,12 @@ +#include <string.h> +#undef strxfrm + +size_t +strxfrm(char * restrict dst, const char * restrict src, size_t n) +{ + size_t len = strlen(src); + + if (len < n) + strcpy(dst, src); + return len; +} diff --git a/src/libc/syscall.h b/src/libc/syscall.h @@ -0,0 +1,8 @@ +extern void *_brk(void *addr); +extern int _open(const char *path, int flags); +extern int _close(int fd); +extern int _read(int fd, void *buf, size_t n); +extern int _write(int fd, void *buf, size_t n); +extern int _lseek(int fd, long off, int whence); +extern void _Exit(int status); +extern int _access(char *path, int mode); diff --git a/src/libc/time/Makefile b/src/libc/time/Makefile @@ -0,0 +1,16 @@ +.POSIX: +PROJECTDIR =../../.. +include $(PROJECTDIR)/scripts/rules.mk + +MORECFLAGS = -w -I$(INCDIR) -I$(INCDIR)/bits/$(SYS) -I$(INCDIR)/bits/$(ARCH) + +OBJS = _daysyear.o\ + asctime.o\ + ctime.o\ + difftime.o\ + gmtime.o\ + localtime.o\ + mktime.o\ + strftime.o\ + +all: $(OBJS) diff --git a/src/libc/time/_daysyear.c b/src/libc/time/_daysyear.c @@ -0,0 +1,30 @@ +#include <time.h> +#include "../libc.h" + +int _daysmon[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + +int +_daysyear(int year) +{ + if (year%4 != 0) + return 365; + if (year%100 == 0 && year%400 != 0) + return 365; + return 366; +} + +/* + * Happy New Year!!!! + */ +int +_newyear(int year) +{ + int day; + + year += 1900 - 1; + day = 1 + year + year/4; + day -= year/100; + day += year/400; + + return day % 7; +} diff --git a/src/libc/time/asctime.c b/src/libc/time/asctime.c @@ -0,0 +1,12 @@ +#include <time.h> +#undef asctime + +#include <stdio.h> // TODO: remove me! +char * +asctime(const struct tm *tm) +{ + static char buf[30]; + + strftime(buf, sizeof(buf), "%c\n", tm); + return buf; +} diff --git a/src/libc/time/ctime.c b/src/libc/time/ctime.c @@ -0,0 +1,8 @@ +#include <time.h> +#undef ctime + +char * +ctime(const time_t *t) +{ + return asctime(localtime(t)); +} diff --git a/src/libc/time/difftime.c b/src/libc/time/difftime.c @@ -0,0 +1,8 @@ +#include <time.h> +#undef difftime + +double +difftime(time_t t1, time_t t2) +{ + return (double) (t1 - t2); +} diff --git a/src/libc/time/gmtime.c b/src/libc/time/gmtime.c @@ -0,0 +1,36 @@ +#include <time.h> + +#include "../libc.h" +#undef gmtime + +struct tm * +gmtime(const time_t *t) +{ + static struct tm tm; + time_t sec, min, hour, year, day; + int i; + + tm.tm_sec = *t % SECDAY; + tm.tm_min = tm.tm_sec / 60; + tm.tm_sec %= 60; + tm.tm_hour = tm.tm_min / 60; + tm.tm_min %= 60; + day = *t / SECDAY; + + tm.tm_wday = (day + THU) % 7; /* 1/1/1970 was Thursday */ + + for (i = EPOCH; day >= _daysyear(i); ++i) + day -= _daysyear(i); + tm.tm_year = i - 1900; + tm.tm_yday = day; + + _daysmon[FEB] = FEBDAYS(tm.tm_year); + for (i = JAN; day > _daysmon[i]; i++) + day -= _daysmon[i]; + tm.tm_mon = i; + tm.tm_mday = day + 1; + + tm.tm_isdst = 0; + + return &tm; +} diff --git a/src/libc/time/localtime.c b/src/libc/time/localtime.c @@ -0,0 +1,22 @@ +#include <time.h> + +#include "../libc.h" +#undef localtime + +struct tm * +localtime(const time_t *timep) +{ + struct tzone *tz; + struct tm *tm; + time_t t = *timep; + + t += tz->gmtoff * 60; + t += tz->isdst * 60; + tm = gmtime(&t); + tz = _tzone(tm); + tm->tm_zone = tz->name; + tm->tm_isdst = tz->isdst; + tm->tm_gmtoff = tz->gmtoff; + + return tm; +} diff --git a/src/libc/time/mktime.c b/src/libc/time/mktime.c @@ -0,0 +1,113 @@ +#include <limits.h> +#include <time.h> + +#include "../libc.h" +#undef mktime + +static int +norm(int *val, int *next, int qty) +{ + int v = *val, n = *next, d; + + if (v < 0) { + d = -v / qty + 1; + v += d * qty; + if (n > INT_MAX - d) + return 0; + n += d; + } + if (v >= qty) { + d = v / qty; + v -= d * qty; + if (n < INT_MIN + d) + return 0; + n -= d; + } + + *val = v; + *next = n; + return 1; +} + +static int +normalize(struct tm *tm) +{ + int mon, day, year; + struct tm aux = *tm; + + if (!norm(&tm->tm_sec, &tm->tm_min, 60) || + !norm(&tm->tm_min, &tm->tm_hour, 60) || + !norm(&tm->tm_hour, &tm->tm_mday, 24) || + !norm(&tm->tm_mon, &tm->tm_year, 12)) { + return 0; + } + + day = tm->tm_mday; + year = EPOCH + tm->tm_year; + _daysmon[FEB] = FEBDAYS(year); + + for (mon = tm->tm_mon; day < 1; --mon) { + day += _daysmon[mon]; + if (mon == JAN) { + if (year == EPOCH) + return -1; + year--; + _daysmon[FEB] = FEBDAYS(year); + mon = DEC+1; + } + } + + for (; day > _daysmon[mon]; ++mon) { + day -= _daysmon[mon]; + if (mon == DEC) { + if (year == _MAXYEAR) + return -1; + year++; + _daysmon[FEB] = FEBDAYS(year); + mon = JAN-1; + } + } + + tm->tm_mon = mon; + tm->tm_year = year - EPOCH; + tm->tm_mday = day; + tm->tm_wday = (_newyear(tm->tm_year) + tm->tm_yday) % 7; + + return 1; +} + +time_t +mktime(struct tm *tm) +{ + int i, year, dst; + time_t t; + struct tm *aux; + + if (!normalize(tm)) + return -1; + + t = 0; + year = tm->tm_year + 1900; + for (i = EPOCH; i < year; i++) + t += _daysyear(i) * SECDAY; + + for (i = 0; i < tm->tm_mon; i++) + t += _daysmon[i] * SECDAY; + + t += tm->tm_sec; + t += tm->tm_min * SECMIN; + t += tm->tm_hour * SECHOUR; + t += (tm->tm_mday-1) * SECDAY; + + aux = localtime(&t); + + dst = 0; + if (tm->tm_isdst == 0 && aux->tm_isdst == 1) + dst = -SECHOUR; + else if (tm->tm_isdst == 1 && aux->tm_isdst == 0) + dst = +SECHOUR; + + t += aux->tm_gmtoff + dst; + + return t; +} diff --git a/src/libc/time/strftime.c b/src/libc/time/strftime.c @@ -0,0 +1,247 @@ +#include <time.h> +#include <string.h> + +#include "../libc.h" +#undef strftime + +static char *days[] = { + "Sunday", "Monday", "Tuesday", "Wednesday", + "Thursday", "Friday", "Saturday", +}; + +static char *months[] = { + "January", "February", "March", "April", + "May", "June", "July", "August", + "September", "October", "November", "December" +}; + +static char *am_pm[] = {"AM", "PM"}; + +static size_t +sval(char *s, size_t siz, char **strs, int abrev, int idx, int max) +{ + char *str; + size_t len; + + if (idx < 0 && idx >= max) + goto wrong; + + str = strs[idx]; + len = (!abrev) ? strlen(str) : 3; + if (len > siz) + goto wrong; + + memcpy(s, str, len); + return len; + +wrong: + *s = '?'; + return 1; +} + +static size_t +dval(char *s, size_t siz, int prec, int fill, int val) +{ + char *t; + int n; + static char digits[] = "0123456789"; + + if (prec > siz || val < 0) { + *s = '?'; + return 1; + } + + n = prec; + do { + s[--n] = digits[val % 10]; + val /= 10; + } while (n > 0 && val > 0); + + while (n > 0) + s[--n] = fill; + + return prec; +} + +static size_t +timezone(char *s, size_t prec, const struct tm * restrict tm) +{ + long off = tm->tm_gmtoff; + + if (prec < 5) { + *s = '?'; + return 1; + } + + if (off >= 0) { + *s++ = '+'; + } else { + *s++ = '-'; + off = -off; + } + + dval(s, 2, 2, '0', off / 3600); + dval(s, 2, 2, '0', (off % 3600) / 60); + + return 5; +} + +size_t +strftime(char * restrict s, size_t siz, + const char * restrict fmt, + const struct tm * restrict tm) +{ + int ch, abrev, val, fill, width; + size_t n, inc; + char *tfmt; + + for (n = siz-1; (ch = *fmt++) && n > 0; s += inc, n -= inc) { + if (ch != '%') { + *s = ch; + inc = 1; + continue; + } + + abrev = 0; + fill = '0'; + width = 2; + + switch (*fmt++) { + case 'Z': + if (!tm->tm_zone) + break; + inc = sval(s, n, &tm->tm_zone, 0, 0, 1); + break; + case 'a': + abrev = 1; + case 'A': + inc = sval(s, n, days, abrev, tm->tm_wday, 7); + break; + case 'h': + case 'b': + abrev = 1; + case 'B': + inc = sval(s, n, months, abrev, tm->tm_mon, 12); + break; + case 'p': + inc = sval(s, n, am_pm, 0, tm->tm_hour > 12, 2); + break; + case 'c': + tfmt = "%a %b %e %T %Y"; + goto recursive; + case 'D': + tfmt = "%m/%d/%y"; + goto recursive; + case 'F': + tfmt = "%Y-%m-%d"; + goto recursive; + case 'R': + tfmt = "%H:%M"; + goto recursive; + case 'X': + case 'T': + tfmt = "%H:%M:%S"; + goto recursive; + case 'r': + tfmt = "%I:%M:%S %p"; + goto recursive; + case 'x': + tfmt = "%m/%d/%y"; + goto recursive; + recursive: + inc = strftime(s, n+1, tfmt, tm) - 1; + break; + case 'n': + val = '\n'; + goto character; + case 't': + val = '\t'; + goto character; + case '%': + val = '%'; + character: + *s = val; + inc = 1; + break; + case 'e': + fill = ' '; + val = tm->tm_mday; + goto number; + case 'd': + val = tm->tm_mday; + goto number; + case 'V': + case 'g': + case 'G': + /* TODO */ + break; + case 'C': + val = tm->tm_year / 100; + goto number; + case 'H': + val = tm->tm_hour; + goto number; + case 'I': + val = tm->tm_hour; + if (val == 0) + val = 12; + if (val > 12) + val -= 12; + goto number; + case 'j': + width = 3; + val = tm->tm_yday+1; + goto number; + case 'm': + val = tm->tm_mon+1; + goto number; + case 'M': + val = tm->tm_min; + goto number; + case 'S': + val = tm->tm_sec; + goto number; + case 'u': + width = 1; + val = tm->tm_wday+1; + goto number; + case 'U': + val = tm->tm_yday / 7; + if (_newyear(tm->tm_year) == SAT) + val++; + goto number; + case 'W': + val = tm->tm_yday / 7; + if (_newyear(tm->tm_year) == MON) + val++; + goto number; + case 'w': + width = 1; + val = tm->tm_wday; + goto number; + case 'y': + val = tm->tm_year%100; + goto number; + case 'Y': + width = 4; + val = 1900 + tm->tm_year; + number: + inc = dval(s, n, width, fill, val); + break; + case 'z': + inc = timezone(s, n, tm); + break; + case 'E': + case 'O': + if (*fmt != '\0') + fmt += 2;; + case '\0': + inc = 0; + --fmt; + break; + } + } + *s = '\0'; + + return siz - n; +} diff --git a/src/libcoff32/Makefile b/src/libcoff32/Makefile @@ -0,0 +1,25 @@ +.POSIX: + +PROJECTDIR = ../.. +include $(PROJECTDIR)/scripts/rules.mk + +OBJS = coff32_pack_hdr.o \ + coff32_unpack_hdr.o \ + coff32_pack_scn.o \ + coff32_unpack_scn.o \ + coff32_pack_aout.o \ + coff32_unpack_aout.o \ + coff32_pack_ent.o \ + coff32_unpack_ent.o \ + +TARGET = $(LIBDIR)/libcoff32.a + +all: $(TARGET) + +$(TARGET): $(OBJS) + $(AR) $(ARFLAGS) $@ $? + ranlib $@ + +dep: inc-dep + +include deps.mk diff --git a/src/libcoff32/coff32_pack_aout.c b/src/libcoff32/coff32_pack_aout.c @@ -0,0 +1,9 @@ +#include <assert.h> + +#include <scc/coff32/aouthdr.h> +#include <scc/coff32/coff32.h> + +void +coff32_pack_aout(packfun fun, unsigned char *buff, AOUTHDR *aout) +{ +} diff --git a/src/libcoff32/coff32_pack_ent.c b/src/libcoff32/coff32_pack_ent.c @@ -0,0 +1,20 @@ +#include <assert.h> + +#include <scc/coff32/syms.h> +#include <scc/coff32/coff32.h> + +void +coff32_pack_ent(packfun fun, unsigned char *buff, SYMENT *ent) +{ + int n; + + n = (*fun)(buff, + "'8lsscc", + &ent->n_name, + &ent->n_value, + &ent->n_scnum, + &ent->n_type, + &ent->n_sclass, + &ent->n_numaux); + assert(n == SYMESZ); +} diff --git a/src/libcoff32/coff32_pack_hdr.c b/src/libcoff32/coff32_pack_hdr.c @@ -0,0 +1,21 @@ +#include <assert.h> + +#include <scc/coff32/filehdr.h> +#include <scc/coff32/coff32.h> + +void +coff32_pack_hdr(packfun fun, unsigned char *buff, FILHDR *hdr) +{ + int n; + + n = (*fun)(buff, + "sslllss", + hdr->f_magic, + hdr->f_nscns, + hdr->f_timdat, + hdr->f_symptr, + hdr->f_nsyms, + hdr->f_opthdr, + hdr->f_flags); + assert(n == FILHSZ); +} diff --git a/src/libcoff32/coff32_pack_scn.c b/src/libcoff32/coff32_pack_scn.c @@ -0,0 +1,24 @@ +#include <assert.h> + +#include <scc/coff32/scnhdr.h> +#include <scc/coff32/coff32.h> + +void +coff32_pack_scn(packfun fun, unsigned char *buff, SCNHDR *scn) +{ + int n; + + n = (*fun)(buff, + "'8llllllssl", + scn->s_name, + scn->s_paddr, + scn->s_vaddr, + scn->s_size, + scn->s_scnptr, + scn->s_relptr, + scn->s_lnnoptr, + scn->s_nrelloc, + scn->s_nlnno, + scn->s_flags); + assert(n == SCNHSZ); +} diff --git a/src/libcoff32/coff32_unpack_aout.c b/src/libcoff32/coff32_unpack_aout.c @@ -0,0 +1,9 @@ +#include <assert.h> + +#include <scc/coff32/aouthdr.h> +#include <scc/coff32/coff32.h> + +void +coff32_unpack_aout(packfun fun, unsigned char *buff, AOUTHDR *ent) +{ +} diff --git a/src/libcoff32/coff32_unpack_ent.c b/src/libcoff32/coff32_unpack_ent.c @@ -0,0 +1,20 @@ +#include <assert.h> + +#include <scc/coff32/syms.h> +#include <scc/coff32/coff32.h> + +void +coff32_unpack_ent(packfun fun, unsigned char *buff, SYMENT *ent) +{ + int n; + + n = (*fun)(buff, + "'8lsscc", + &ent->n_name, + &ent->n_value, + &ent->n_scnum, + &ent->n_type, + &ent->n_sclass, + &ent->n_numaux); + assert(n == SYMESZ); +} diff --git a/src/libcoff32/coff32_unpack_hdr.c b/src/libcoff32/coff32_unpack_hdr.c @@ -0,0 +1,22 @@ +#include <assert.h> + +#include <scc/coff32/filehdr.h> +#include <scc/coff32/coff32.h> + +void +coff32_unpack_hdr(packfun fun, unsigned char *buff, FILHDR *hdr) +{ + int n; + + n = (*fun)(buff, + "sslllss", + &hdr->f_magic, + &hdr->f_nscns, + &hdr->f_timdat, + &hdr->f_symptr, + &hdr->f_nsyms, + &hdr->f_opthdr, + &hdr->f_flags); + assert(n == FILHSZ); +} + diff --git a/src/libcoff32/coff32_unpack_scn.c b/src/libcoff32/coff32_unpack_scn.c @@ -0,0 +1,24 @@ +#include <assert.h> + +#include <scc/coff32/scnhdr.h> +#include <scc/coff32/coff32.h> + +void +coff32_unpack_scn(packfun fun, unsigned char *buff, SCNHDR *scn) +{ + int n; + + n = (*fun)(buff, + "'8llllllssl", + scn->s_name, + &scn->s_paddr, + &scn->s_vaddr, + &scn->s_size, + &scn->s_scnptr, + &scn->s_relptr, + &scn->s_lnnoptr, + &scn->s_nrelloc, + &scn->s_nlnno, + &scn->s_flags); + assert(n == SCNHSZ); +} diff --git a/src/libcoff32/deps.mk b/src/libcoff32/deps.mk @@ -0,0 +1,17 @@ +#deps +coff32_pack_aout.o: $(INCDIR)/scc/scc/coff32/aouthdr.h +coff32_pack_aout.o: $(INCDIR)/scc/scc/coff32/coff32.h +coff32_pack_ent.o: $(INCDIR)/scc/scc/coff32/coff32.h +coff32_pack_ent.o: $(INCDIR)/scc/scc/coff32/syms.h +coff32_pack_hdr.o: $(INCDIR)/scc/scc/coff32/coff32.h +coff32_pack_hdr.o: $(INCDIR)/scc/scc/coff32/filehdr.h +coff32_pack_scn.o: $(INCDIR)/scc/scc/coff32/coff32.h +coff32_pack_scn.o: $(INCDIR)/scc/scc/coff32/scnhdr.h +coff32_unpack_aout.o: $(INCDIR)/scc/scc/coff32/aouthdr.h +coff32_unpack_aout.o: $(INCDIR)/scc/scc/coff32/coff32.h +coff32_unpack_ent.o: $(INCDIR)/scc/scc/coff32/coff32.h +coff32_unpack_ent.o: $(INCDIR)/scc/scc/coff32/syms.h +coff32_unpack_hdr.o: $(INCDIR)/scc/scc/coff32/coff32.h +coff32_unpack_hdr.o: $(INCDIR)/scc/scc/coff32/filehdr.h +coff32_unpack_scn.o: $(INCDIR)/scc/scc/coff32/coff32.h +coff32_unpack_scn.o: $(INCDIR)/scc/scc/coff32/scnhdr.h diff --git a/src/libcrt/Makefile b/src/libcrt/Makefile @@ -0,0 +1,11 @@ +.POSIX: +PROJECTDIR=../.. +include $(PROJECTDIR)/scripts/rules.mk + +OBJS = crt-$(SYS).o crt-$(ABI).o +TARGET = $(CRTDIR)/$(ARCH)-$(SYS)/crt.o + +all: $(TARGET) + +$(TARGET): $(OBJS) + $(LD) -r -o $@ $(OBJS) diff --git a/src/libcrt/crt-amd64-posix.s b/src/libcrt/crt-amd64-posix.s @@ -0,0 +1,19 @@ + .bss + .globl _environ +_environ: + .quad 0 + + .text + .global _start +_start: + movq %rsp,%rbp + + /* load argc, argv, envp from stack */ + movq (%rbp),%rdi /* argc */ + leaq 8(%rbp),%rsi /* argv */ + leaq 16(%rbp,%rdi,8),%rdx /* envp = argv + 8*argc + 8 */ + movq %rdx,_environ + + call main + movl %eax,%edi + jmp exit diff --git a/src/libcrt/crt-arm32-posix.s b/src/libcrt/crt-arm32-posix.s @@ -0,0 +1,16 @@ + .bss + .globl _environ +_environ: + .word 0 + + .text + .globl _start +_start: + ldr r0,[sp] /* argc */ + add r1,sp,#4 /* argv */ + add r2,r1,r0,lsl #2 /* argv = argc + 4*argc + 4 */ + add r2,r2,#4 + ldr r3,=_environ + str r2,[r3] + bl main + b exit diff --git a/src/libcrt/crt-arm64-posix.s b/src/libcrt/crt-arm64-posix.s @@ -0,0 +1,16 @@ + .bss + .globl _environ +_environ: + .quad 0 + + .text + .globl _start +_start: + ldr x0,[sp] /* argc */ + add x1,sp,#8 /* argv */ + add x2,x1,x0,lsl #3 /* argv = argc + 8*argc + 8 */ + add x2,x2,#8 + adr x3,_environ + str x2,[x3] + bl main + b exit diff --git a/src/libcrt/crt-dragonfly.s b/src/libcrt/crt-dragonfly.s @@ -0,0 +1 @@ + .file "crt-dragonfly.s" diff --git a/src/libcrt/crt-linux.s b/src/libcrt/crt-linux.s @@ -0,0 +1 @@ + .file "crt-linux.s" diff --git a/src/libcrt/crt-netbsd.s b/src/libcrt/crt-netbsd.s @@ -0,0 +1,9 @@ + .file "crt-netbsd.s" + .section ".note.netbsd.ident", "a" + .p2align 2 + + .long 7 + .long 4 + .long 1 + .ascii "NetBSD\0\0" + .long 800000000 diff --git a/src/libcrt/crt-openbsd.s b/src/libcrt/crt-openbsd.s @@ -0,0 +1,9 @@ + .file "crt-openbsd.s" + .section ".note.openbsd.ident", "a" + .p2align 2 + .long 8 + .long 4 + .long 1 + .ascii "OpenBSD\0" + .long 0 + .p2align 2 diff --git a/src/libscc/Makefile b/src/libscc/Makefile @@ -0,0 +1,31 @@ + +PROJECTDIR = ../.. +include $(PROJECTDIR)/scripts/rules.mk + +OBJS = debug.o \ + die.o \ + newitem.o \ + xcalloc.o \ + xmalloc.o \ + xrealloc.o \ + xstrdup.o \ + alloc.o \ + casecmp.o \ + lunpack.o \ + lpack.o \ + bunpack.o \ + bpack.o \ + wmyro.o \ + rmyro.o \ + +TARGET = $(LIBDIR)/libscc.a + +all: $(TARGET) + +$(TARGET): $(OBJS) + $(AR) $(ARFLAGS) $@ $? + ranlib $@ + +dep: inc-dep + +include deps.mk diff --git a/src/libscc/alloc.c b/src/libscc/alloc.c @@ -0,0 +1,112 @@ +static char sccsid[] = "@(#) ./lib/scc/alloc.c"; +#include <stdlib.h> +#include <scc/scc.h> + +/* + * This is the most pedantic piece of code that I have written + * in my life. The next union is used to enforce the aligmnet + * of the address returned by new(). A union has the aligment + * of the field with the biggest aligment. This union has all + * the types that we use in scc, and we round all the address + * to the aligment of this struct, so we can be sure that any + * pointer using that address will be safe. The field ap is + * in the union to be sure that struct pointers are included + * in the list, although they will have the same aligment or + * smaller than void *, but I wanted to be pedantic. + */ +union hdr { + union hdr *next; + struct arena *ap; + char c; + unsigned char uc; + int i; + short s; + long l; + long long ll; + float f; + double d; + long double ld; + void *vp; +}; + +struct arena { + struct arena *next; + union hdr *array; +}; + +struct alloc { + size_t size; + size_t nmemb; + size_t padding; + struct arena *arena; + union hdr *freep; +}; + +static void +newarena(Alloc *allocp) +{ + struct arena *ap; + union hdr *bp, *lim; + size_t unit, n = allocp->nmemb; + + unit = (allocp->size-1) / sizeof(union hdr) + 1; + ap = xmalloc(sizeof(struct arena)); + ap->array = xmalloc(unit * sizeof(union hdr) * n); + + bp = ap->array; + for (lim = &bp[unit * (n-1)]; bp < lim; bp += unit) + bp->next = bp + unit; + bp->next = NULL; + + ap->next = allocp->arena; + allocp->arena = ap; + allocp->freep = ap->array; +} + +Alloc * +alloc(size_t size, size_t nmemb) +{ + Alloc *allocp = xmalloc(sizeof(*allocp)); + + allocp->size = size; + allocp->nmemb = nmemb; + allocp->arena = NULL; + allocp->freep = NULL; + + return allocp; +} + +void +dealloc(Alloc *allocp) +{ + struct arena *ap, *next; + + for (ap = allocp->arena; ap; ap = next) { + next = ap->next; + free(ap->array); + free(ap); + } + free(allocp); +} + +void * +new(Alloc *allocp) +{ + union hdr *bp; + + if (!allocp->freep) + newarena(allocp); + bp = allocp->freep; + allocp->freep = bp->next; + + return bp; +} + +void +delete(Alloc *allocp, void *p) +{ + union hdr *bp = p; + + bp->next = allocp->freep; + allocp->freep = bp; +} diff --git a/src/libscc/bpack.c b/src/libscc/bpack.c @@ -0,0 +1,64 @@ +#include <ctype.h> +#include <stdarg.h> + +#include <scc/scc.h> + +int +bpack(unsigned char *dst, char *fmt, ...) +{ + unsigned char *bp, *cp; + unsigned s; + unsigned long l; + unsigned long long q; + size_t n; + int d; + va_list va; + + bp = dst; + va_start(va, fmt); + while (*fmt) { + switch (*fmt++) { + case '\'': + for (n = 0; isdigit(*fmt); n += d) { + n *= 10; + d = *fmt++ - '0'; + } + cp = va_arg(va, unsigned char *); + while (n--) + *bp++ = *cp++; + break; + case 'c': + *bp++ = va_arg(va, unsigned); + break; + case 's': + s = va_arg(va, unsigned); + *bp++ = s >> 8; + *bp++ = s; + break; + case 'l': + l = va_arg(va, unsigned long); + *bp++ = l >> 24; + *bp++ = l >> 16; + *bp++ = l >> 8; + *bp++ = l; + break; + case 'q': + q = va_arg(va, unsigned long long); + *bp++ = q >> 56; + *bp++ = q >> 48; + *bp++ = q >> 40; + *bp++ = q >> 32; + *bp++ = q >> 24; + *bp++ = q >> 16; + *bp++ = q >> 8; + *bp++ = q; + break; + default: + va_end(va); + return -1; + } + } + va_end(va); + + return bp - dst; +} diff --git a/src/libscc/bunpack.c b/src/libscc/bunpack.c @@ -0,0 +1,71 @@ +static char sccsid[] = "@(#) ./lib/scc/lunpack.c"; + +#include <ctype.h> +#include <stdarg.h> + +#include <scc/scc.h> + +int +lunpack(unsigned char *src, char *fmt, ...) +{ + unsigned char *bp, *cp; + unsigned short *sp; + unsigned s; + unsigned long *lp, l; + unsigned long long *qp, q; + va_list va; + size_t n; + int d; + + bp = src; + va_start(va, fmt); + while (*fmt) { + switch (*fmt++) { + case '\'': + for (n = 0; isdigit(*fmt); n += d) { + n *= 10; + d = *fmt++ - '0'; + } + cp = va_arg(va, unsigned char *); + while (n--) + *cp++ = *bp++; + break; + case 'c': + cp = va_arg(va, unsigned char *); + *cp = *bp++; + break; + case 's': + sp = va_arg(va, unsigned short *); + s = (unsigned) *bp++ << 8; + s |= (unsigned) *bp++; + *sp = s; + break; + case 'l': + lp = va_arg(va, unsigned long *); + l = (unsigned long) *bp++ << 24; + l |= (unsigned long) *bp++ << 16; + l |= (unsigned long) *bp++ << 8; + l |= (unsigned long) *bp++; + *lp = l; + break; + case 'q': + qp = va_arg(va, unsigned long long *); + q = (unsigned long long) *bp++ << 56; + q |= (unsigned long long) *bp++ << 48; + q |= (unsigned long long) *bp++ << 40; + q |= (unsigned long long) *bp++ << 32; + q |= (unsigned long long) *bp++ << 24; + q |= (unsigned long long) *bp++ << 16; + q |= (unsigned long long) *bp++ << 8; + q |= (unsigned long long) *bp++; + *qp = q; + break; + default: + va_end(va); + return -1; + } + } + va_end(va); + + return bp - src; +} diff --git a/src/libscc/casecmp.c b/src/libscc/casecmp.c @@ -0,0 +1,11 @@ +static char sccsid[] = "@(#) ./lib/scc/casecmp.c"; +#include <ctype.h> +#include <scc/scc.h> + +int +casecmp(const char *s1, const char *s2) +{ + while (*s1 && toupper(*s1) == toupper(*s2)) + ++s1, ++s2; + return *s1 - *s2; +} diff --git a/src/libscc/debug.c b/src/libscc/debug.c @@ -0,0 +1,20 @@ +static char sccsid[] = "@(#) ./lib/scc/debug.c"; +#include <stdarg.h> +#include <stdio.h> + +#include <scc/scc.h> + +int debug; + +void +dbg(const char *fmt, ...) +{ + if (!debug) + return; + va_list va; + va_start(va, fmt); + vfprintf(stderr, fmt, va); + putc('\n', stderr); + va_end(va); + return; +} diff --git a/src/libscc/deps.mk b/src/libscc/deps.mk @@ -0,0 +1,18 @@ +#deps +alloc.o: $(INCDIR)/scc/scc/scc.h +bpack.o: $(INCDIR)/scc/scc/scc.h +bunpack.o: $(INCDIR)/scc/scc/scc.h +casecmp.o: $(INCDIR)/scc/scc/scc.h +debug.o: $(INCDIR)/scc/scc/scc.h +die.o: $(INCDIR)/scc/scc/scc.h +lpack.o: $(INCDIR)/scc/scc/scc.h +lunpack.o: $(INCDIR)/scc/scc/scc.h +newitem.o: $(INCDIR)/scc/scc/scc.h +rmyro.o: $(INCDIR)/scc/scc/myro.h +rmyro.o: $(INCDIR)/scc/scc/scc.h +wmyro.o: $(INCDIR)/scc/scc/myro.h +wmyro.o: $(INCDIR)/scc/scc/scc.h +xcalloc.o: $(INCDIR)/scc/scc/scc.h +xmalloc.o: $(INCDIR)/scc/scc/scc.h +xrealloc.o: $(INCDIR)/scc/scc/scc.h +xstrdup.o: $(INCDIR)/scc/scc/scc.h diff --git a/src/libscc/die.c b/src/libscc/die.c @@ -0,0 +1,20 @@ +static char sccsid[] = "@(#) ./lib/scc/die.c"; +#include <stdarg.h> +#include <stdlib.h> +#include <stdio.h> + +#include <scc/scc.h> + +int failure; + +void +die(const char *fmt, ...) +{ + failure = 1; + va_list va; + va_start(va, fmt); + vfprintf(stderr, fmt, va); + putc('\n', stderr); + va_end(va); + exit(1); +} diff --git a/src/libscc/lpack.c b/src/libscc/lpack.c @@ -0,0 +1,64 @@ +#include <ctype.h> +#include <stdarg.h> + +#include <scc/scc.h> + +int +lpack(unsigned char *dst, char *fmt, ...) +{ + unsigned char *bp, *cp; + unsigned s; + unsigned long l; + unsigned long long q; + size_t n; + int d; + va_list va; + + bp = dst; + va_start(va, fmt); + while (*fmt) { + switch (*fmt++) { + case '\'': + for (n = 0; isdigit(*fmt); n += d) { + n *= 10; + d = *fmt++ - '0'; + } + cp = va_arg(va, unsigned char *); + while (n--) + *bp++ = *cp++; + break; + case 'c': + *bp++ = va_arg(va, unsigned); + break; + case 's': + s = va_arg(va, unsigned); + *bp++ = s; + *bp++ = s >> 8; + break; + case 'l': + l = va_arg(va, unsigned long); + *bp++ = l; + *bp++ = l >> 8; + *bp++ = l >> 16; + *bp++ = l >> 24; + break; + case 'q': + q = va_arg(va, unsigned long long); + *bp++ = q; + *bp++ = q >> 8; + *bp++ = q >> 16; + *bp++ = q >> 24; + *bp++ = q >> 32; + *bp++ = q >> 40; + *bp++ = q >> 48; + *bp++ = q >> 56; + break; + default: + va_end(va); + return -1; + } + } + va_end(va); + + return bp - dst; +} diff --git a/src/libscc/lunpack.c b/src/libscc/lunpack.c @@ -0,0 +1,71 @@ +static char sccsid[] = "@(#) ./lib/scc/lunpack.c"; + +#include <ctype.h> +#include <stdarg.h> + +#include <scc/scc.h> + +int +lunpack(unsigned char *src, char *fmt, ...) +{ + unsigned char *bp, *cp; + unsigned short *sp; + unsigned s; + unsigned long *lp, l; + unsigned long long *qp, q; + va_list va; + size_t n; + int d; + + bp = src; + va_start(va, fmt); + while (*fmt) { + switch (*fmt++) { + case '\'': + for (n = 0; isdigit(*fmt); n += d) { + n *= 10; + d = *fmt++ - '0'; + } + cp = va_arg(va, unsigned char *); + while (n--) + *cp++ = *bp++; + break; + case 'c': + cp = va_arg(va, unsigned char *); + *cp = *bp++; + break; + case 's': + sp = va_arg(va, unsigned short *); + s = (unsigned) *bp++; + s |= (unsigned) *bp++ << 8; + *sp = s; + break; + case 'l': + lp = va_arg(va, unsigned long *); + l = (unsigned long) *bp++; + l |= (unsigned long) *bp++ << 8; + l |= (unsigned long) *bp++ << 16; + l |= (unsigned long) *bp++ << 24; + *lp = l; + break; + case 'q': + qp = va_arg(va, unsigned long long *); + q = (unsigned long long) *bp++; + q |= (unsigned long long) *bp++ << 8; + q |= (unsigned long long) *bp++ << 16; + q |= (unsigned long long) *bp++ << 24; + q |= (unsigned long long) *bp++ << 32; + q |= (unsigned long long) *bp++ << 40; + q |= (unsigned long long) *bp++ << 48; + q |= (unsigned long long) *bp++ << 56; + *qp = q; + break; + default: + va_end(va); + return -1; + } + } + va_end(va); + + return bp - src; +} diff --git a/src/libscc/newitem.c b/src/libscc/newitem.c @@ -0,0 +1,12 @@ +#include <scc/scc.h> + +void +newitem(struct items *items, char *item) +{ + if ((items->n + 1) < items->n) + die("overflow in newitem (%u + 1)", items->n); + + items->s = xrealloc(items->s, (items->n + 1) * sizeof(char **)); + items->s[items->n++] = item; +} + diff --git a/src/libscc/rmyro.c b/src/libscc/rmyro.c @@ -0,0 +1,94 @@ +static char sccsid[] = "@(#) ./lib/scc/rmyro.c"; + +#include <assert.h> +#include <stdio.h> +#include <string.h> + +#include <scc/scc.h> +#include <scc/myro.h> + +int +rdmyrohdr(FILE *fp, struct myrohdr *hdr) +{ + unsigned char buf[MYROHDR_SIZ]; + int len; + + fread(buf, sizeof(buf), 1, fp); + if (ferror(fp)) + return EOF; + len = lunpack(buf, "cccclqqqqq", + hdr->magic+0, hdr->magic+1, + hdr->magic+2, hdr->magic+3, + &hdr->format, + &hdr->entry, + &hdr->strsize, + &hdr->secsize, + &hdr->symsize, + &hdr->relsize); + assert(len == MYROHDR_SIZ); + + return len; +} + +int +rdmyrosec(FILE *fp, struct myrosect *sect) +{ + unsigned char buf[MYROSECT_SIZ]; + int len; + + fread(buf, sizeof(buf), 1, fp); + if (ferror(fp)) + return EOF; + len = lunpack(buf, "lsccqq", + &sect->name, + &sect->flags, + &sect->fill, + &sect->aligment, + &sect->offset, + &sect->len); + assert(len == MYROSECT_SIZ); + + return len; +} + +int +rdmyrosym(FILE *fp, struct myrosym *sym) +{ + unsigned char buf[MYROSYM_SIZ]; + int len; + + fread(buf, sizeof(buf), 1, fp); + if (ferror(fp)) + return EOF; + len = lunpack(buf, "llccqq", + &sym->name, + &sym->type, + &sym->section, + &sym->flags, + &sym->offset, + &sym->len); + assert(len == MYROSYM_SIZ); + + return len; +} + +int +rdmyrorel(FILE *fp, struct myrorel *rel) +{ + unsigned char buf[MYROREL_SIZ]; + int len; + + fread(buf, sizeof(buf), 1, fp); + if (ferror(fp)) + return EOF; + len = lunpack(buf, "lccccq", + &rel->id, + &rel->flags, + &rel->size, + &rel->nbits, + &rel->shift, + &rel->offset); + assert(len == MYROREL_SIZ); + + return len; +} diff --git a/src/libscc/wmyro.c b/src/libscc/wmyro.c @@ -0,0 +1,86 @@ +static char sccsid[] = "@(#) ./lib/scc/wmyro.c"; + +#include <assert.h> +#include <stdio.h> +#include <string.h> + +#include <scc/scc.h> +#include <scc/myro.h> + +int +wrmyrohdr(FILE *fp, struct myrohdr *hdr) +{ + unsigned char buf[MYROHDR_SIZ]; + int len; + + len = lpack(buf, "cccclqqqqq", + hdr->magic[0], hdr->magic[1], + hdr->magic[2], hdr->magic[3], + hdr->format, + hdr->entry, + hdr->strsize, + hdr->secsize, + hdr->symsize, + hdr->relsize); + assert(MYROHDR_SIZ == len); + fwrite(buf, len, 1, fp); + + return (ferror(fp)) ? EOF : len; +} + +int +wrmyrosec(FILE *fp, struct myrosect *sect) +{ + unsigned char buf[MYROSECT_SIZ]; + int len; + + len = lpack(buf, "lsccqq", + sect->name, + sect->flags, + sect->fill, + sect->aligment, + sect->offset, + sect->len); + assert(MYROSECT_SIZ == len); + fwrite(buf, len, 1, fp); + + return (ferror(fp)) ? EOF : len; +} + +int +wrmyrosym(FILE *fp, struct myrosym *sym) +{ + unsigned char buf[MYROSYM_SIZ]; + int len; + + len = lpack(buf, "llccqq", + sym->name, + sym->type, + sym->section, + sym->flags, + sym->offset, + sym->len); + assert(MYROSYM_SIZ == len); + fwrite(buf, len, 1, fp); + + return (ferror(fp)) ? EOF : len; +} + +int +wrmyrorel(FILE *fp, struct myrorel *rel) +{ + unsigned char buf[MYROREL_SIZ]; + int len; + + len = lpack(buf, "lccccq", + rel->id, + rel->flags, + rel->size, + rel->nbits, + rel->shift, + rel->offset); + assert(MYROREL_SIZ == len); + fwrite(buf, len, 1, fp); + + return (ferror(fp)) ? EOF : len; +} diff --git a/src/libscc/xcalloc.c b/src/libscc/xcalloc.c @@ -0,0 +1,13 @@ +static char sccsid[] = "@(#) ./lib/scc/xcalloc.c"; +#include <stdlib.h> +#include <scc/scc.h> + +void * +xcalloc(size_t n, size_t size) +{ + void *p = calloc(n, size); + + if (!p) + die("out of memory"); + return p; +} diff --git a/src/libscc/xmalloc.c b/src/libscc/xmalloc.c @@ -0,0 +1,13 @@ +static char sccsid[] = "@(#) ./lib/scc/xmalloc.c"; +#include <stdlib.h> +#include <scc/scc.h> + +void * +xmalloc(size_t size) +{ + void *p = malloc(size); + + if (!p) + die("out of memory"); + return p; +} diff --git a/src/libscc/xrealloc.c b/src/libscc/xrealloc.c @@ -0,0 +1,13 @@ +static char sccsid[] = "@(#) ./lib/scc/xrealloc.c"; +#include <stdlib.h> +#include <scc/scc.h> + +void * +xrealloc(void *buff, size_t size) +{ + void *p = realloc(buff, size); + + if (!p) + die("out of memory"); + return p; +} diff --git a/src/libscc/xstrdup.c b/src/libscc/xstrdup.c @@ -0,0 +1,12 @@ +static char sccsid[] = "@(#) ./lib/scc/xstrdup.c"; +#include <string.h> +#include <scc/scc.h> + +char * +xstrdup(const char *s) +{ + size_t len = strlen(s) + 1; + char *p = xmalloc(len); + + return memcpy(p, s, len); +} diff --git a/src/nm/Makefile b/src/nm/Makefile @@ -0,0 +1,21 @@ +.POSIX: + +PROJECTDIR = ../.. +include $(PROJECTDIR)/scripts/rules.mk + +OBJS = main.o \ + coff32.o \ + formats.o \ + +TARGET = $(BINDIR)/nm + +all: $(TARGET) + +$(TARGET): $(LIBDIR)/libscc.a + +$(TARGET): $(OBJS) + $(CC) $(SCC_LDFLAGS) $(OBJS) -lscc -o $@ + +dep: inc-dep + +include deps.mk diff --git a/src/nm/coff32.c b/src/nm/coff32.c @@ -0,0 +1,312 @@ +static char sccsid[] = "@(#) ./nm/coff.c"; + +#include <assert.h> +#include <ctype.h> +#include <errno.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <scc/coff32/filehdr.h> +#include <scc/coff32/scnhdr.h> +#include <scc/coff32/syms.h> +#include <scc/scc.h> +#include "nm.h" + +static int (*unpack)(unsigned char *, char *, ...); +static long strtbl, symtbl, sectbl; +static SCNHDR *sections; +static struct symbol *syms; +static size_t nsect, nsyms; + +static char +typeof(SYMENT *ent) +{ + SCNHDR *sec; + int c; + long flags; + + switch (ent->n_scnum) { + case N_DEBUG: + c = 'n'; + break; + case N_ABS: + c = 'a'; + break; + case N_UNDEF: + c = (ent->n_value != 0) ? 'C' : 'U'; + break; + default: + if (ent->n_scnum > nsect) + die("nm: incorrect section index"); + sec = &sections[ent->n_scnum-1]; + flags = sec->s_flags; + if (flags & STYP_TEXT) + c = 't'; + else if (flags & STYP_DATA) + c = 'd'; + else if (flags & STYP_BSS) + c = 'b'; + else + c = '?'; + break; + } + + if (ent->n_sclass == C_EXT) + c = toupper(c); + + return c; +} + +static char * +getsname(char *fname, FILE *fp, SYMENT *ent) +{ + int c; + size_t len; + char *s, *err; + fpos_t pos; + + if (ent->n_zeroes != 0) { + for (len = 0; len < E_SYMNMLEN && ent->n_name[len]; ++len) + ; + s = xmalloc(len+1); + s[len] = '\0'; + return memcpy(s, ent->n_name, len); + } + + /* TODO: read the string table in memory before reading symbols */ + fgetpos(fp, &pos); + fseek(fp, strtbl, SEEK_SET); + fseek(fp, ent->n_offset, SEEK_CUR); + + if (ferror(fp)) + goto error; + + s = NULL; + for (len = 1; (c = getc(fp)) != EOF; len++) { + s = xrealloc(s, len); + if ((s[len-1] = c) == '\0') + break; + } + if (c == EOF) + goto error; + fsetpos(fp, &pos); + return s; + +error: + err = (!ferror(fp)) ? + "EOF before reading strings" : strerror(errno); + die("nm: %s: %s", fname, err); +} + +static void +getfsym(unsigned char *buff, SYMENT *ent) +{ + int n; + + n = (*unpack)(buff, + "'8lsscc", + &ent->n_name, + &ent->n_value, + &ent->n_scnum, + &ent->n_type, + &ent->n_sclass, + &ent->n_numaux); + assert(n == SYMESZ); +} + +static void +getsymbol(char *fname, FILE *fp, + unsigned char *buff, SYMENT *ent, struct symbol *sym) +{ + char *nam; + + getfsym(buff, ent); + nam = ent->n_name; + if (nam[0] == 0 && nam[1] == 0 && nam[2] == 0 && nam[3] == 0) { + long zero, offset; + + (*unpack)(nam, "ll", &zero, &offset); + ent->n_zeroes = zero; + ent->n_offset = offset; + } + sym->name = getsname(fname, fp, ent); + sym->type = typeof(ent); + sym->value = ent->n_value; + sym->size = (sym->type == 'C') ? ent->n_value : 0; +} + +static void +getsyms(char *fname, char *member, FILE *fp, FILHDR *hdr) +{ + size_t n, i; + unsigned aux; + unsigned char buff[SYMESZ]; + SYMENT ent; + + if (hdr->f_nsyms > SIZE_MAX) + die("nm: %s:Too many symbols\n", member); + + n = hdr->f_nsyms; + syms = xcalloc(sizeof(*syms), n); + + if (fseek(fp, symtbl, SEEK_SET) == EOF) + die("nm: %s:%s", fname, strerror(errno)); + + aux = nsyms = 0; + for (i = 0; i < n; i++) { + if (fread(buff, SYMESZ, 1, fp) != 1) + break; + if (aux > 0) { + aux--; + continue; + } + getsymbol(member, fp, buff, &ent, &syms[nsyms++]); + aux = ent.n_numaux; + } + if (n != i) { + char *err; + + err = (!ferror(fp)) ? + "EOF before reading symbols" : strerror(errno); + die("nm: %s: %s", fname, err); + } +} + +static void +getfsec(unsigned char *buff, SCNHDR *sec) +{ + int n; + + n = (*unpack)(buff, + "'8llllllssl", + sec->s_name, + &sec->s_paddr, + &sec->s_vaddr, + &sec->s_size, + &sec->s_scnptr, + &sec->s_relptr, + &sec->s_lnnoptr, + &sec->s_nrelloc, + &sec->s_nlnno, + &sec->s_flags); + assert(n == SCNHSZ); +} + +static void +getsects(char *fname, char *member, FILE *fp, FILHDR *hdr) +{ + size_t i; + char buff[SCNHSZ]; + + nsect = hdr->f_nscns; + if (nsect == 0) + return; + + if (nsect > SIZE_MAX) + die("nm: %s:Too many sections\n", member); + + if (fseek(fp, sectbl, SEEK_SET) == EOF) + die("nm: %s:%s", member, strerror(errno)); + + sections = xcalloc(sizeof(*sections), nsect); + for (i = 0; i < nsect; i++) { + if (fread(buff, SCNHSZ, 1, fp) != 1) + break; + getfsec(buff, &sections[i]); + } + if (i != nsect) { + char *err; + + err = (!ferror(fp)) ? + "EOF before reading sections" : strerror(errno); + die("nm: %s: %s", fname, err); + } +} + +static void +getfhdr(unsigned char *buff, FILHDR *hdr) +{ + int n; + + n = (*unpack)(buff, + "sslllss", + &hdr->f_magic, + &hdr->f_nscns, + &hdr->f_timdat, + &hdr->f_symptr, + &hdr->f_nsyms, + &hdr->f_opthdr, + &hdr->f_flags); + assert(n == FILHSZ); +} + +static int +nm(char *fname, char *member, FILE *fp) +{ + unsigned char buff[FILHSZ]; + FILHDR hdr; + long pos = ftell(fp); + + if (fread(buff, FILHSZ, 1, fp) != 1) { + if (!ferror(fp)) + return 0; + die("nm: %s: %s", fname, strerror(errno)); + } + + getfhdr(buff, &hdr); + if ((hdr.f_flags & F_SYMS) != 0 || hdr.f_nsyms == 0) { + fprintf(stderr, "nm: %s: no symbols\n", member); + return 1; + } + + /* TODO: Check overflow */ + strtbl = pos + hdr.f_symptr + hdr.f_nsyms* SYMESZ; + symtbl = pos + hdr.f_symptr; + sectbl = pos + FILHSZ + hdr.f_opthdr; + + getsects(fname, member, fp, &hdr); + getsyms(fname, member, fp, &hdr); + printsyms(fname, member, syms, nsyms); + + free(sections); + free(syms); + return 1; +} + +static int +probe(char *fname, char *member, FILE *fp) +{ + int c; + int c1, c2; + fpos_t pos; + unsigned short magic; + + fgetpos(fp, &pos); + c1 = getc(fp); + c2 = getc(fp); + fsetpos(fp, &pos); + + if (ferror(fp)) + die("nm: %s: %s", fname, strerror(errno)); + + if (c1 == EOF || c2 == EOF) + return 0; + magic = c1 | c2 << 8; + + switch (magic) { + case COFF_I386MAGIC: + case COFF_Z80MAGIC: + unpack = lunpack; + return 1; + default: + unpack = NULL; + return 0; + } +} + +struct objfile coff32 = { + .probe = probe, + .nm = nm, +}; diff --git a/src/nm/deps.mk b/src/nm/deps.mk @@ -0,0 +1,11 @@ +#deps +coff32.o: $(INCDIR)/scc/scc/coff32/filehdr.h +coff32.o: $(INCDIR)/scc/scc/coff32/scnhdr.h +coff32.o: $(INCDIR)/scc/scc/coff32/syms.h +coff32.o: $(INCDIR)/scc/scc/scc.h +coff32.o: nm.h +formats.o: nm.h +main.o: $(INCDIR)/scc/scc/ar.h +main.o: $(INCDIR)/scc/scc/arg.h +main.o: $(INCDIR)/scc/scc/scc.h +main.o: nm.h diff --git a/src/nm/formats.c b/src/nm/formats.c @@ -0,0 +1,13 @@ +static char sccsid[] = "@(#) ./nm/probe.c"; + +#include <stdio.h> + +#include "nm.h" + +/* TODO: Autogenerate this file */ +struct objfile coff32; + +struct objfile *formats[] = { + &coff32, + NULL, +}; diff --git a/src/nm/main.c b/src/nm/main.c @@ -0,0 +1,272 @@ +static char sccsid[] = "@(#) ./nm/main.c"; + +#include <ctype.h> +#include <errno.h> +#include <limits.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <scc/arg.h> +#include <scc/scc.h> +#include <scc/ar.h> +#include "nm.h" + +char *argv0; +static int radix = 16; +static int Pflag; +static int Aflag; +static int vflag; +static int gflag; +static int uflag; +static int arflag; + +static int +object(char *fname, char *member, FILE *fp) +{ + extern struct objfile *formats[]; + struct objfile **p, *obj; + void *data; + + for (p = formats; *p; ++p) { + obj = *p; + if ((*obj->probe)(fname, member, fp)) + break; + } + if (*p == NULL) + return 0; + return (*obj->nm)(fname, member, fp); +} + +static char * +getfname(struct ar_hdr *hdr, char *dst) +{ + char *p; + int i; + + memcpy(dst, hdr->ar_name, SARNAM); + dst[SARNAM] = '\0'; + + for (i = SARNAM-1; i >= 0; i--) { + if (dst[i] != ' ' && dst[i] != '/') + break; + dst[i] = '\0'; + } + return dst; +} + +static void +ar(char *fname, FILE *fp) +{ + struct ar_hdr hdr; + long pos, siz; + char member[SARNAM+1]; + + arflag = 1; + if (fseek(fp, SARMAG, SEEK_SET) == EOF) + goto file_error; + + while (fread(&hdr, sizeof(hdr), 1, fp) == 1) { + pos = ftell(fp); + if (strncmp(hdr.ar_fmag, ARFMAG, sizeof(hdr.ar_fmag))) + goto corrupted; + + siz = 0; + sscanf(hdr.ar_size, "%10ld", &siz); + if (siz == 0) + goto corrupted; + + if (siz & 1) + siz++; + if (pos == -1 || pos > LONG_MAX - siz) + die("nm: %s: overflow in size of archive", fname); + pos += siz; + + getfname(&hdr, member); + if (!object(fname, member, fp)) { + fprintf(stderr, + "nm: skipping member %s in archive %s\n", + member, fname); + } + if (fseek(fp, pos, SEEK_SET) == EOF) + goto file_error; + } + if (ferror(fp)) + goto file_error; + return; + +corrupted: + die("nm: %s: corrupted archive", fname); +file_error: + die("nm: %s: %s", fname, strerror(errno)); +} + +static int +archive(char *fname, FILE *fp) +{ + char magic[SARMAG]; + fpos_t pos; + + fgetpos(fp, &pos); + fread(magic, SARMAG, 1, fp); + fsetpos(fp, &pos); + + if (ferror(fp)) + die("nm: %s: %s", fname, strerror(errno)); + if (strncmp(magic, ARMAG, SARMAG) != 0) + return 0; + + ar(fname, fp); + return 1; +} + +static void +printsym(char *file, char *member, struct symbol *sym) +{ + char *fmt; + int type = sym->type; + + if (type == '?') + return; + + if (uflag && type != 'U') + return; + + if (gflag && !isupper(type)) + return; + + if (Aflag) + printf((arflag) ? "%s[%s]: " : "%s: ", file, member); + if (Pflag) { + printf("%s %c", sym->name, sym->type); + if (type != 'U') { + if (radix == 8) + fmt = " %016.16llo %lo"; + else if (radix == 10) + fmt = " %016.16llu %lu"; + else + fmt = " %016.16llx %lx"; + printf(fmt, sym->value, sym->size); + } + } else { + if (type == 'U') + fmt = " "; + else if (radix == 8) + fmt = "%016.16llo"; + else if (radix == 10) + fmt = "%016.16lld"; + else + fmt = "%016.16llx"; + printf(fmt, sym->value); + printf(" %c %s", sym->type, sym->name); + } + putchar('\n'); +} + +static int +cmp(const void *p1, const void *p2) +{ + const struct symbol *s1 = p1, *s2 = p2; + + if (vflag) { + if (s1->value > s2->value) + return 1; + if (s1->value < s2->value) + return -1; + if (s1->type == 'U' && s2->type == 'U') + return 0; + if (s1->type == 'U') + return -1; + if (s2->type == 'U') + return 1; + return 0; + } else { + return strcmp(s1->name, s2->name); + } +} + +void +printsyms(char *file, char *member, struct symbol *syms, size_t nsyms) +{ + qsort(syms, nsyms, sizeof(*syms), cmp); + + while (nsyms--) + printsym(file, member, syms++); +} + +static void +doit(char *fname) +{ + FILE *fp; + + arflag = 0; + + if ((fp = fopen(fname, "rb")) == NULL) + die("nm: %s: %s", fname, strerror(errno)); + + if (!object(fname, fname, fp) && !archive(fname, fp)) + die("nm: %s: File format not recognized", fname); + + if (ferror(fp)) + die("nm: %s: %s", fname, strerror(errno)); + + fclose(fp); +} + +static void +usage(void) +{ + fputs("nm [-APv][ -g| -u][-t format] [file...]\n", stderr); + exit(1); +} + +int +main(int argc, char *argv[]) +{ + char *t; + + ARGBEGIN { + case 'P': + Pflag = 1; + break; + case 'A': + Aflag = 1; + break; + case 'g': + gflag = 1; + break; + case 'u': + uflag = 1; + break; + case 'v': + vflag = 1; + break; + case 't': + t = EARGF(usage()); + if (!strcmp(t, "o")) + radix = 8; + else if (!strcmp(t, "d")) + radix = 10; + else if (!strcmp(t, "x")) + radix = 16; + else + usage(); + break; + default: + usage(); + } ARGEND + + if (argc == 0) { + doit("a.out"); + } else { + for ( ; *argv; ++argv) + doit(*argv); + } + + fflush(stdout); + if (ferror(stdout)) + die("nm: error writing in output"); + + return 0; +} diff --git a/src/nm/nm.h b/src/nm/nm.h @@ -0,0 +1,14 @@ +struct symbol { + char *name; + int type; + unsigned long long value; + unsigned long size; +}; + +struct objfile { + int (*probe)(char *fname, char *member, FILE *fp); + int (*nm)(char *fname, char *member, FILE *fp); +}; + +/* main.c */ +extern void printsyms(char *, char *, struct symbol *, size_t ); diff --git a/src/objdump/Makefile b/src/objdump/Makefile @@ -0,0 +1,16 @@ +.POSIX: + +PROJECTDIR = ../.. +include $(PROJECTDIR)/scripts/rules.mk + +OBJS = main.o +TARGET = $(BINDIR)/objdump + +all: $(TARGET) + +$(TARGET): $(OBJS) $(LIBDIR)/libscc.a + $(CC) $(SCC_LDFLAGS) $(OBJS) -lscc -o $@ + +dep: inc-dep + +include deps.mk diff --git a/src/objdump/deps.mk b/src/objdump/deps.mk @@ -0,0 +1,4 @@ +#deps +main.o: $(INCDIR)/scc/scc/arg.h +main.o: $(INCDIR)/scc/scc/myro.h +main.o: $(INCDIR)/scc/scc/scc.h diff --git a/src/objdump/main.c b/src/objdump/main.c @@ -0,0 +1,333 @@ +#include <errno.h> +#include <limits.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <scc/arg.h> +#include <scc/scc.h> +#include <scc/myro.h> + +char *argv0; +static char *strings; +static size_t strsiz; + +struct obj_info { + char *fname; + FILE *fp; + struct myrohdr hdr; + fpos_t strpos; + fpos_t secpos; + fpos_t sympos; + fpos_t relpos; + fpos_t datapos; +}; + +static char * +getstring(unsigned long off) +{ + size_t n; + + if ((int32_t) off == -1) + return ""; + if (off < SIZE_MAX) { + for (n = off; n < strsiz && strings[n]; ++n) + ; + if (n < strsiz) + return &strings[off]; + } + fprintf(stderr, "objdump: wrong string offset %lu\n", off); + return ""; +} + +static int +printhdr(struct obj_info *obj) +{ + struct myrohdr *hdr = &obj->hdr; + + printf("header:\n" + " magic: %02x %02x %02x %02x \"%4.4s\"\n" + " format: %lu (\"%s\")\n" + " entry: %llu\n" + " string table size: %llu\n" + " section table size: %llu\n" + " symbol table size: %llu\n" + " relocation table size: %llu\n", + hdr->magic[0], hdr->magic[1], + hdr->magic[2], hdr->magic[3], + hdr->magic, + hdr->format, getstring(hdr->format), + hdr->entry, + hdr->strsize, + hdr->secsize, + hdr->symsize, + hdr->relsize); + return 0; +} + +static int +printstrings(struct obj_info *obj) +{ + size_t off, begin;; + char *s = NULL; + + puts("strings:"); + for (off = 0; off < strsiz; off++) { + if (s == NULL) { + s = &strings[off]; + begin = off; + } + if (strings[off] == '\0') { + printf(" [%zd] \"%s\"\n", begin, s); + s = NULL; + } + } + return 0; +} + +static char * +sectflags(struct myrosect *sec) +{ + static char flags[10]; + char *s = flags + sizeof(flags); + + if (sec->flags & MYROSEC_LOAD) + *--s = 'L'; + if (sec->flags & MYROSEC_FILE) + *--s = 'F'; + if (sec->flags & MYROSEC_ABS) + *--s = 'A'; + if (sec->flags & MYROSEC_EXEC) + *--s = 'X'; + if (sec->flags & MYROSEC_WRITE) + *--s = 'W'; + if (sec->flags & MYROSEC_READ) + *--s = 'R'; + return s; +} + +static int +printsections(struct obj_info *obj) +{ + unsigned long long n, i; + struct myrosect sect; + struct myrohdr *hdr = &obj->hdr; + + printf("sections:\n" + " [Nr]\t%s\t%-16s\t%-16s\t%s\t%s\t%s\n", + "Name", + "Offset", + "Size", + "Fill", + "Align", + "Flags"); + + n = hdr->secsize / MYROSECT_SIZ; + for (i = 0; i < n; ++i) { + if (rdmyrosec(obj->fp, &sect) < 0) + return -1; + printf(" [%2llu]\t%s\t%016llX\t%016llX\t%02X\t%u\t%s\n", + i, + getstring(sect.name), + sect.offset, + sect.len, + sect.fill, + sect.aligment, + sectflags(&sect)); + } + return 0; +} + +static char * +symflags(struct myrosym *sym) +{ + static char flags[10]; + char *s = flags + sizeof(flags); + + if (sym->flags & MYROSYM_COMMON) + *--s = 'C'; + if (sym->flags & MYROSYM_EXTERN) + *--s = 'G'; + if (sym->flags & MYROSYM_UNDEF) + *s-- = 'U'; + return s; +} + +static int +printsymbols(struct obj_info *obj) +{ + unsigned long long n, i; + struct myrosym sym; + struct myrohdr *hdr = &obj->hdr; + + printf("symbols:\n" + " [Nr]\t%s\t%-16s\t%s\t%s\t%s\t%s\n", + "Name", + "Value", + "Section", + "Flags", + "Size", + "Type"); + n = hdr->symsize / MYROSYM_SIZ; + for (i = 0; i < n; ++i) { + if (rdmyrosym(obj->fp, &sym) < 0) + return -1; + printf(" [%2llu]\t%s\t%016llX\t%u\t%s\t%llu\t%s\n", + i, + getstring(sym.name), + sym.offset, + sym.section, + symflags(&sym), + sym.len, + getstring(sym.type)); + } + return 0; +} + +static int +printrelocs(struct obj_info *obj) +{ + unsigned long long n, i; + struct myrorel rel; + struct myrohdr *hdr = &obj->hdr; + + printf("relocs:\n" + " [Nr]\t%-16s\tType\tId\tSize\tNbits\tShift\n", + "Offset"); + n = hdr->relsize / MYROREL_SIZ; + for (i = 0; i < n; ++i) { + if (rdmyrorel(obj->fp, &rel) < 0) + return -1; + printf(" [%2llu]\t%016llX\t%s\t%lu\t%u\t%u\t%u\n", + i, + rel.offset, + (rel.id & 1<<31) ? "section" : "symbol", + rel.id & ~(1<<31), + rel.size, + rel.nbits, + rel.shift); + } + return 0; +} + +static int +printdata(struct obj_info *obj) +{ + unsigned long long off; + int c, i, j; + + puts("data:"); + for (off = 0; ; off += 32) { + printf(" %016llX:", off); + for (i = 0; i < 2; i++) { + for (j = 0; j < 8; j++) { + if ((c = getc(obj->fp)) == EOF) + goto exit_loop; + printf(" %02X", c); + } + putchar('\t'); + } + putchar('\n'); + } + +exit_loop: + putchar('\n'); + return (ferror(obj->fp)) ? -1 : 0; +} + +void +dump(char *fname, FILE *fp) +{ + struct obj_info obj; + struct myrohdr *hdr; + + obj.fname = fname; + obj.fp = fp; + hdr = &obj.hdr; + + if (rdmyrohdr(obj.fp, hdr) < 0) + goto wrong_file; + if (strncmp(hdr->magic, MYROMAGIC, MYROMAGIC_SIZ)) { + fprintf(stderr, + "objdump: %s: File format not recognized\n", + fname); + return; + } + puts(fname); + if (hdr->strsize > SIZE_MAX) { + fprintf(stderr, + "objdump: %s: overflow in header\n", + fname); + return; + } + strsiz = hdr->strsize; + + if (strsiz > 0) { + strings = xmalloc(strsiz); + fread(strings, strsiz, 1, fp); + if (feof(fp)) + goto wrong_file; + } + + if (printhdr(&obj) < 0) + goto wrong_file; + if (printstrings(&obj) < 0) + goto wrong_file; + if (printsections(&obj) < 0) + goto wrong_file; + if (printsymbols(&obj) < 0) + goto wrong_file; + if (printrelocs(&obj) < 0) + goto wrong_file; + if (printdata(&obj) < 0) + goto wrong_file; + return; + +wrong_file: + fprintf(stderr, + "objdump: %s: %s\n", + fname, strerror(errno)); +} + +void +doit(char *fname) +{ + FILE *fp; + + if ((fp = fopen(fname, "rb")) == NULL) { + fprintf(stderr, "objdump: %s: %s\n", fname, strerror(errno)); + return; + } + dump(fname, fp); + fclose(fp); +} + +void +usage(void) +{ + fputs("usage: objdump file ...\n", stderr); + exit(1); +} + +int +main(int argc, char *argv[]) +{ + ARGBEGIN { + default: + usage(); + } ARGEND + + if (argc == 0) + doit("a.out"); + else while (*argv) { + free(strings); + strings = NULL; + doit(*argv++); + } + + if (fclose(stdout) == EOF) + die("objdump: stdout: %s", strerror(errno)); + + return 0; +} diff --git a/tests/Makefile b/tests/Makefile @@ -1,7 +1,7 @@ .POSIX: PROJECTDIR = .. -include $(PROJECTDIR)/rules.mk +include $(PROJECTDIR)/scripts/rules.mk DIRS=ar/execute \ nm/execute \