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:
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, §);
- }
-
- 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",
- §->name,
- §->flags,
- §->fill,
- §->aligment,
- §->offset,
- §->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 = §ions[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, §ions[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, §) < 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(§));
- }
- 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, §);
+ }
+
+ 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",
+ §->name,
+ §->flags,
+ §->fill,
+ §->aligment,
+ §->offset,
+ §->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 = §ions[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, §ions[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, §) < 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(§));
+ }
+ 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 \