commit c2e3e1046098b43cbf23b24a257e3de8c80cd1a8
parent 6218545883ea27f0e1461887c4cf75df923db4fa
Author: erai <erai@omiltem.net>
Date: Mon, 24 Mar 2025 18:18:11 +0000
fold attic back into main tree
Diffstat:
34 files changed, 726 insertions(+), 9497 deletions(-)
diff --git a/.build.yml b/.build.yml
@@ -6,6 +6,7 @@ sources:
tasks:
- bootstrap: "cd os && time ./bootstrap.sh"
- build: "cd os && time ./build.sh"
+ - test: "cd os && time ./test.sh"
- cloc: "cd os && ./cloc.sh"
triggers:
- action: email
diff --git a/.gitignore b/.gitignore
@@ -1,29 +1,11 @@
-a.out
-kernel
-disk
-cc[012]
-cc2.c
-parse3.om
-parsepeg.om
-pxe
-cmp
-cpio
-echo
-find
-ls
-rm
-sh
-sshd
-vi
-as
-initramfs
-mv
-mkdir
-xxd
-cat
-peg
-peg0
-*.out*
-*_peg.c
-*.lines
-*.call
+*
+!*.om
+!*.sh
+!*.vim
+!.build.yml
+!.gitignore
+!LICENSE
+!README.md
+!cc0.c
+!check.py
+!pxe.asm
diff --git a/aes.om b/aes.om
@@ -0,0 +1,162 @@
+// https://doi.org/10.6028/NIST.FIPS.197-upd1
+
+func aes_expand(w: *byte, key: *byte) {
+ var i: int;
+ var j: int;
+ var aes_sb: *byte;
+ var aes_rc: *byte;
+
+ aes_sb = "c|w{\xf2ko\xc50\x01g+\xfe\xd7\xabv\xca\x82\xc9}\xfaYG\xf0\xad\xd4\xa2\xaf\x9c\xa4r\xc0\xb7\xfd\x93&6?\xf7\xcc4\xa5\xe5\xf1q\xd81\x15\x04\xc7#\xc3\x18\x96\x05\x9a\x07\x12\x80\xe2\xeb'\xb2u\t\x83,\x1a\x1bnZ\xa0R;\xd6\xb3)\xe3/\x84S\xd1\x00\xed \xfc\xb1[j\xcb\xbe9JLX\xcf\xd0\xef\xaa\xfbCM3\x85E\xf9\x02\x7fP<\x9f\xa8Q\xa3@\x8f\x92\x9d8\xf5\xbc\xb6\xda!\x10\xff\xf3\xd2\xcd\x0c\x13\xec_\x97D\x17\xc4\xa7~=d]\x19s`\x81O\xdc\"*\x90\x88F\xee\xb8\x14\xde^\x0b\xdb\xe02:\nI\x06$\\\xc2\xd3\xacb\x91\x95\xe4y\xe7\xc87m\x8d\xd5N\xa9lV\xf4\xeaez\xae\x08\xbax%.\x1c\xa6\xb4\xc6\xe8\xddt\x1fK\xbd\x8b\x8ap>\xb5fH\x03\xf6\x0ea5W\xb9\x86\xc1\x1d\x9e\xe1\xf8\x98\x11i\xd9\x8e\x94\x9b\x1e\x87\xe9\xceU(\xdf\x8c\xa1\x89\r\xbf\xe6BhA\x99-\x0f\xb0T\xbb\x16";
+ aes_rc = "\x01\x02\x04\x08\x10 @\x80\x1b6";
+
+ i = 0;
+ loop {
+ if i == 16 {
+ break;
+ }
+
+ w[i] = key[i];
+
+ i = i + 1;
+ }
+
+ j = 0;
+ loop {
+ if j == 10 {
+ break;
+ }
+
+ w[i] = w[i - 16] ^ aes_sb[w[i - 3]] ^ aes_rc[j]; i = i + 1;
+ w[i] = w[i - 16] ^ aes_sb[w[i - 3]]; i = i + 1;
+ w[i] = w[i - 16] ^ aes_sb[w[i - 3]]; i = i + 1;
+ w[i] = w[i - 16] ^ aes_sb[w[i - 7]]; i = i + 1;
+
+ w[i] = w[i - 16] ^ w[i - 4]; i = i + 1;
+ w[i] = w[i - 16] ^ w[i - 4]; i = i + 1;
+ w[i] = w[i - 16] ^ w[i - 4]; i = i + 1;
+ w[i] = w[i - 16] ^ w[i - 4]; i = i + 1;
+
+ w[i] = w[i - 16] ^ w[i - 4]; i = i + 1;
+ w[i] = w[i - 16] ^ w[i - 4]; i = i + 1;
+ w[i] = w[i - 16] ^ w[i - 4]; i = i + 1;
+ w[i] = w[i - 16] ^ w[i - 4]; i = i + 1;
+
+ w[i] = w[i - 16] ^ w[i - 4]; i = i + 1;
+ w[i] = w[i - 16] ^ w[i - 4]; i = i + 1;
+ w[i] = w[i - 16] ^ w[i - 4]; i = i + 1;
+ w[i] = w[i - 16] ^ w[i - 4]; i = i + 1;
+
+ j = j + 1;
+ }
+}
+
+func aes_two(x: byte): byte {
+ var a: int;
+ a = x as int;
+ a = (a << 1) ^ ((a >> 7) * 0x1b);
+ return a as byte;
+}
+
+struct _aes {
+ a: int;
+ b: int;
+}
+
+func aes_cipher(cipher: *byte, plain: *byte, w: *byte) {
+ var tmp: _aes;
+ var s: *byte;
+ var t: byte;
+ var abcd: byte;
+ var i: int;
+ var j: int;
+ var aes_sb: *byte;
+
+ s = (&tmp) as *byte;
+
+ aes_sb = "c|w{\xf2ko\xc50\x01g+\xfe\xd7\xabv\xca\x82\xc9}\xfaYG\xf0\xad\xd4\xa2\xaf\x9c\xa4r\xc0\xb7\xfd\x93&6?\xf7\xcc4\xa5\xe5\xf1q\xd81\x15\x04\xc7#\xc3\x18\x96\x05\x9a\x07\x12\x80\xe2\xeb'\xb2u\t\x83,\x1a\x1bnZ\xa0R;\xd6\xb3)\xe3/\x84S\xd1\x00\xed \xfc\xb1[j\xcb\xbe9JLX\xcf\xd0\xef\xaa\xfbCM3\x85E\xf9\x02\x7fP<\x9f\xa8Q\xa3@\x8f\x92\x9d8\xf5\xbc\xb6\xda!\x10\xff\xf3\xd2\xcd\x0c\x13\xec_\x97D\x17\xc4\xa7~=d]\x19s`\x81O\xdc\"*\x90\x88F\xee\xb8\x14\xde^\x0b\xdb\xe02:\nI\x06$\\\xc2\xd3\xacb\x91\x95\xe4y\xe7\xc87m\x8d\xd5N\xa9lV\xf4\xeaez\xae\x08\xbax%.\x1c\xa6\xb4\xc6\xe8\xddt\x1fK\xbd\x8b\x8ap>\xb5fH\x03\xf6\x0ea5W\xb9\x86\xc1\x1d\x9e\xe1\xf8\x98\x11i\xd9\x8e\x94\x9b\x1e\x87\xe9\xceU(\xdf\x8c\xa1\x89\r\xbf\xe6BhA\x99-\x0f\xb0T\xbb\x16";
+
+ i = 0;
+ loop {
+ if i == 16 {
+ break;
+ }
+
+ s[i] = plain[i] ^ w[i];
+
+ i = i + 1;
+ }
+
+ j = 1;
+ loop {
+ if j == 10 {
+ break;
+ }
+
+ i = 0;
+ loop {
+ if i == 16 {
+ break;
+ }
+
+ s[i] = aes_sb[s[i]];
+
+ i = i + 1;
+ }
+
+ t=s[1]; s[1]=s[5]; s[5]=s[9]; s[9]=s[13];s[13]=t;
+ t=s[2]; s[2]=s[10]; s[10]=t; t=s[6];s[6]=s[14];s[14]=t;
+ t=s[15];s[15]=s[11];s[11]=s[7]; s[7]=s[3]; s[3]=t;
+
+ i = 0;
+ loop {
+ if i == 16 {
+ break;
+ }
+
+ t = s[i]; abcd = s[i] ^ s[i + 1] ^ s[i + 2] ^ s[i + 3];
+ s[i] = s[i] ^ abcd ^ aes_two(s[i] ^ s[i + 1]);
+ s[i + 1] = s[i + 1] ^ abcd ^ aes_two(s[i + 1] ^ s[i + 2]);
+ s[i + 2] = s[i + 2] ^ abcd ^ aes_two(s[i + 2] ^ s[i + 3]);
+ s[i + 3] = s[i + 3] ^ abcd ^ aes_two(s[i + 3] ^ t);
+
+ i = i + 4;
+ }
+
+ i = 0;
+ loop {
+ if i == 16 {
+ break;
+ }
+
+ s[i] = s[i] ^ w[j * 16 + i];
+
+ i = i + 1;
+ }
+
+ j = j + 1;
+ }
+
+ loop {
+ if i == 16 {
+ break;
+ }
+
+ s[i] = aes_sb[s[i]];
+
+ i = i + 1;
+ }
+
+ t=s[1]; s[1]=s[5]; s[5]=s[9]; s[9]=s[13];s[13]=t;
+ t=s[2]; s[2]=s[10]; s[10]=t; t=s[6];s[6]=s[14];s[14]=t;
+ t=s[15];s[15]=s[11];s[11]=s[7]; s[7]=s[3]; s[3]=t;
+
+ loop {
+ if i == 16 {
+ break;
+ }
+
+ cipher[i] = s[i] ^ w[i + 10 * 16];
+
+ i = i + 1;
+ }
+}
diff --git a/aes_test.om b/aes_test.om
@@ -0,0 +1,8 @@
+func main(argc: int, argv: **byte, envp: **byte) {
+ var key: *byte;
+ var w: *byte;
+ var cipher: *byte;
+ var plain: *byte;
+ aes_expand(w, key);
+ aes_cipher(cipher, plain, w);
+}
diff --git a/attic/aes.om b/attic/aes.om
@@ -1,162 +0,0 @@
-// https://doi.org/10.6028/NIST.FIPS.197-upd1
-
-aes_expand(w: *byte, key: *byte) {
- var i: int;
- var j: int;
- var aes_sb: *byte;
- var aes_rc: *byte;
-
- aes_sb = "c|w{\xf2ko\xc50\x01g+\xfe\xd7\xabv\xca\x82\xc9}\xfaYG\xf0\xad\xd4\xa2\xaf\x9c\xa4r\xc0\xb7\xfd\x93&6?\xf7\xcc4\xa5\xe5\xf1q\xd81\x15\x04\xc7#\xc3\x18\x96\x05\x9a\x07\x12\x80\xe2\xeb'\xb2u\t\x83,\x1a\x1bnZ\xa0R;\xd6\xb3)\xe3/\x84S\xd1\x00\xed \xfc\xb1[j\xcb\xbe9JLX\xcf\xd0\xef\xaa\xfbCM3\x85E\xf9\x02\x7fP<\x9f\xa8Q\xa3@\x8f\x92\x9d8\xf5\xbc\xb6\xda!\x10\xff\xf3\xd2\xcd\x0c\x13\xec_\x97D\x17\xc4\xa7~=d]\x19s`\x81O\xdc\"*\x90\x88F\xee\xb8\x14\xde^\x0b\xdb\xe02:\nI\x06$\\\xc2\xd3\xacb\x91\x95\xe4y\xe7\xc87m\x8d\xd5N\xa9lV\xf4\xeaez\xae\x08\xbax%.\x1c\xa6\xb4\xc6\xe8\xddt\x1fK\xbd\x8b\x8ap>\xb5fH\x03\xf6\x0ea5W\xb9\x86\xc1\x1d\x9e\xe1\xf8\x98\x11i\xd9\x8e\x94\x9b\x1e\x87\xe9\xceU(\xdf\x8c\xa1\x89\r\xbf\xe6BhA\x99-\x0f\xb0T\xbb\x16";
- aes_rc = "\x01\x02\x04\x08\x10 @\x80\x1b6";
-
- i = 0;
- loop {
- if i == 16 {
- break;
- }
-
- w[i] = key[i];
-
- i = i + 1;
- }
-
- j = 0;
- loop {
- if j == 10 {
- break;
- }
-
- w[i] = w[i - 16] ^ aes_sb[w[i - 3]] ^ aes_rc[j]; i = i + 1;
- w[i] = w[i - 16] ^ aes_sb[w[i - 3]]; i = i + 1;
- w[i] = w[i - 16] ^ aes_sb[w[i - 3]]; i = i + 1;
- w[i] = w[i - 16] ^ aes_sb[w[i - 7]]; i = i + 1;
-
- w[i] = w[i - 16] ^ w[i - 4]; i = i + 1;
- w[i] = w[i - 16] ^ w[i - 4]; i = i + 1;
- w[i] = w[i - 16] ^ w[i - 4]; i = i + 1;
- w[i] = w[i - 16] ^ w[i - 4]; i = i + 1;
-
- w[i] = w[i - 16] ^ w[i - 4]; i = i + 1;
- w[i] = w[i - 16] ^ w[i - 4]; i = i + 1;
- w[i] = w[i - 16] ^ w[i - 4]; i = i + 1;
- w[i] = w[i - 16] ^ w[i - 4]; i = i + 1;
-
- w[i] = w[i - 16] ^ w[i - 4]; i = i + 1;
- w[i] = w[i - 16] ^ w[i - 4]; i = i + 1;
- w[i] = w[i - 16] ^ w[i - 4]; i = i + 1;
- w[i] = w[i - 16] ^ w[i - 4]; i = i + 1;
-
- j = j + 1;
- }
-}
-
-aes_two(x: byte): byte {
- var a: int;
- a = x:int;
- a = (a << 1) ^ ((a >> 7) * 0x1b);
- return a:byte;
-}
-
-struct _aes {
- a: int;
- b: int;
-}
-
-aes_cipher(cipher: *byte, plain: *byte, w: *byte) {
- var tmp: _aes;
- var s: *byte;
- var t: byte;
- var abcd: byte;
- var i: int;
- var j: int;
- var aes_sb: *byte;
-
- s = (&tmp):*byte;
-
- aes_sb = "c|w{\xf2ko\xc50\x01g+\xfe\xd7\xabv\xca\x82\xc9}\xfaYG\xf0\xad\xd4\xa2\xaf\x9c\xa4r\xc0\xb7\xfd\x93&6?\xf7\xcc4\xa5\xe5\xf1q\xd81\x15\x04\xc7#\xc3\x18\x96\x05\x9a\x07\x12\x80\xe2\xeb'\xb2u\t\x83,\x1a\x1bnZ\xa0R;\xd6\xb3)\xe3/\x84S\xd1\x00\xed \xfc\xb1[j\xcb\xbe9JLX\xcf\xd0\xef\xaa\xfbCM3\x85E\xf9\x02\x7fP<\x9f\xa8Q\xa3@\x8f\x92\x9d8\xf5\xbc\xb6\xda!\x10\xff\xf3\xd2\xcd\x0c\x13\xec_\x97D\x17\xc4\xa7~=d]\x19s`\x81O\xdc\"*\x90\x88F\xee\xb8\x14\xde^\x0b\xdb\xe02:\nI\x06$\\\xc2\xd3\xacb\x91\x95\xe4y\xe7\xc87m\x8d\xd5N\xa9lV\xf4\xeaez\xae\x08\xbax%.\x1c\xa6\xb4\xc6\xe8\xddt\x1fK\xbd\x8b\x8ap>\xb5fH\x03\xf6\x0ea5W\xb9\x86\xc1\x1d\x9e\xe1\xf8\x98\x11i\xd9\x8e\x94\x9b\x1e\x87\xe9\xceU(\xdf\x8c\xa1\x89\r\xbf\xe6BhA\x99-\x0f\xb0T\xbb\x16";
-
- i = 0;
- loop {
- if i == 16 {
- break;
- }
-
- s[i] = plain[i] ^ w[i];
-
- i = i + 1;
- }
-
- j = 1;
- loop {
- if j == 10 {
- break;
- }
-
- i = 0;
- loop {
- if i == 16 {
- break;
- }
-
- s[i] = aes_sb[s[i]];
-
- i = i + 1;
- }
-
- t=s[1]; s[1]=s[5]; s[5]=s[9]; s[9]=s[13];s[13]=t;
- t=s[2]; s[2]=s[10]; s[10]=t; t=s[6];s[6]=s[14];s[14]=t;
- t=s[15];s[15]=s[11];s[11]=s[7]; s[7]=s[3]; s[3]=t;
-
- i = 0;
- loop {
- if i == 16 {
- break;
- }
-
- t = s[i]; abcd = s[i] ^ s[i + 1] ^ s[i + 2] ^ s[i + 3];
- s[i] = s[i] ^ abcd ^ aes_two(s[i] ^ s[i + 1]);
- s[i + 1] = s[i + 1] ^ abcd ^ aes_two(s[i + 1] ^ s[i + 2]);
- s[i + 2] = s[i + 2] ^ abcd ^ aes_two(s[i + 2] ^ s[i + 3]);
- s[i + 3] = s[i + 3] ^ abcd ^ aes_two(s[i + 3] ^ t);
-
- i = i + 4;
- }
-
- i = 0;
- loop {
- if i == 16 {
- break;
- }
-
- s[i] = s[i] ^ w[j * 16 + i];
-
- i = i + 1;
- }
-
- j = j + 1;
- }
-
- loop {
- if i == 16 {
- break;
- }
-
- s[i] = aes_sb[s[i]];
-
- i = i + 1;
- }
-
- t=s[1]; s[1]=s[5]; s[5]=s[9]; s[9]=s[13];s[13]=t;
- t=s[2]; s[2]=s[10]; s[10]=t; t=s[6];s[6]=s[14];s[14]=t;
- t=s[15];s[15]=s[11];s[11]=s[7]; s[7]=s[3]; s[3]=t;
-
- loop {
- if i == 16 {
- break;
- }
-
- cipher[i] = s[i] ^ w[i + 10 * 16];
-
- i = i + 1;
- }
-}
diff --git a/attic/cc0.om b/attic/cc0.om
@@ -1,5005 +0,0 @@
-#define _POSIX_C_SOURCE 1
-#include <stdlib.h>
-#include <stdio.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-///////////////////////////////////////////////////////////////////////////////
-// Forward Declarations //
-///////////////////////////////////////////////////////////////////////////////
-
-FILE *fin;
-FILE *fout;
-
-int nc;
-unsigned char *filename;
-int lineno;
-struct node;
-struct type;
-struct label;
-struct fix;
-struct sdecl;
-
-void feed(void);
-struct node *type(void);
-struct node *stmt_list(void);
-struct node *expr(void);
-struct label *mklabel(void);
-void compute_struct(struct sdecl *s);
-int type_sizeof(struct type *t);
-void addfixup(struct label *l);
-
-///////////////////////////////////////////////////////////////////////////////
-// Helpers //
-///////////////////////////////////////////////////////////////////////////////
-
-void
-die(char *msg)
-{
- fprintf(stderr, "die(%s:%d): %s\n", filename, lineno, msg);
- exit(1);
-}
-
-void
-open_output(unsigned char *name)
-{
- int fd;
-
- filename = name;
-
- if (fout != stdout) {
- die("multiple output files");
- }
-
- unlink((char *)name);
-
- fd = open((char *)name, 64 + 1, (7 << 6) + (7 << 3) + 7);
- if (fd < 0) {
- die("failed to open output");
- }
-
- fout = fdopen(fd, "wb");
-}
-
-void
-open_source(unsigned char *name)
-{
- int fd;
-
- if (fin != stdin) {
- die("invalid");
- }
-
- filename = name;
-
- fd = open((char *)name, 0, 0);
- if (fd < 0) {
- die("failed to open file");
- }
-
- fin = fdopen(fd, "rb");
- lineno = 1;
-
- nc = fgetc(fin);
- feed();
-}
-
-void
-close_source(void)
-{
- if (fin != stdin) {
- fclose(fin);
- fin = stdin;
- }
- fin = stdin;
-}
-
-// strlen-ish
-int
-slen(unsigned char *s)
-{
- int i;
-
- i = 0;
- while (1) {
- if (s[i] == 0) {
- return i;
- }
-
- i = i + 1;
- }
-}
-
-// strcmp-ish
-int
-cmp(unsigned char *a, unsigned char *b)
-{
- int i;
-
- i = 0;
- while (1) {
- if (a[i] > b[i]) {
- return 1;
- }
-
- if (a[i] < b[i]) {
- return -1;
- }
-
- if (a[i] == 0) {
- return 0;
- }
-
- i = i + 1;
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Lexer //
-///////////////////////////////////////////////////////////////////////////////
-
-enum {
- T_EOF,
- T_IDENT,
- T_NUM,
- T_HEX,
- T_STR,
- T_CHAR,
- T_LPAR,
- T_RPAR,
- T_LBRA,
- T_RBRA,
- T_COMMA,
- T_SEMI,
- T_COLON,
- T_STAR,
- T_DOT,
- T_NOT,
- T_ASSIGN,
- T_AMP,
- T_OR,
- T_XOR,
- T_LT,
- T_GT,
- T_LE,
- T_GE,
- T_EQ,
- T_NE,
- T_ADD,
- T_SUB,
- T_LSH,
- T_RSH,
- T_BANG,
- T_BOR,
- T_BAND,
- T_LSQ,
- T_RSQ,
- T_DIV,
- T_MOD,
-};
-
-// The token from the source
-unsigned char token[4096];
-
-// Token type
-int tt;
-
-// Token length
-int tlen;
-
-// Single character lookahead
-int nc;
-
-// Line number of the start of the current token
-int lineno;
-
-// Read in an identifier
-void
-feed_ident(void)
-{
- tt = T_IDENT;
- while (1) {
- if (!((nc >= 'a' && nc <= 'z') ||
- (nc >= 'A' && nc <= 'Z') ||
- (nc >= '0' && nc <= '9') ||
- nc == '_')) {
- break;
- }
- if (tlen == sizeof(token) - 1) {
- die("identifier too long");
- }
- token[tlen] = nc;
- tlen = tlen + 1;
- nc = fgetc(fin);
- }
- token[tlen] = 0;
-}
-
-// Parse a hex digit
-int
-hexdig(int c)
-{
- if (c >= '0' && c <= '9') {
- return c - '0';
- }
-
- if (c >= 'A' && c <= 'F') {
- return c - 'F' + 10;
- }
-
- if (c >= 'a' && c <= 'f') {
- return c - 'a' + 10;
- }
-
- die("invalid hex digit");
- return 0;
-}
-
-// Parse an escape and replace nc with the value
-void
-feed_escape(void)
-{
- int hex;
-
- nc = fgetc(fin);
- if (nc == 't') {
- nc = '\t';
- } else if (nc == 'r') {
- nc = '\r';
- } else if (nc == 'n') {
- nc = '\n';
- } else if (nc == 'x') {
- nc = fgetc(fin);
- hex = hexdig(nc) * 16;
-
- nc = fgetc(fin);
- hex = hex + hexdig(nc);
-
- nc = hex;
- } else if (nc != '\\' && nc != '\'' && nc != '"') {
- die("invalid escape");
- }
-}
-
-// Read in a string
-void
-feed_str(void)
-{
- tt = T_STR;
- nc = fgetc(fin);
- while (1) {
- if (nc == '"') {
- token[tlen] = 0;
- nc = fgetc(fin);
- return;
- }
-
- if (nc == EOF) {
- die("eof in string literal");
- }
-
- if (nc == 0 || nc == '\n') {
- die("invalid char in string");
- }
-
- if (tlen == sizeof(token) - 1) {
- die("string too long");
- }
-
- if (nc == '\\') {
- feed_escape();
- }
-
- token[tlen] = nc;
- tlen = tlen + 1;
- nc = fgetc(fin);
- }
-}
-
-// Read in a character
-void
-feed_char(void)
-{
- tt = T_CHAR;
- nc = fgetc(fin);
-
- if (nc == 0 || nc == EOF || nc == '\'' || nc == '\n') {
- die("invalid char");
- }
-
- if (nc == '\\') {
- feed_escape();
- }
-
- token[tlen] = nc;
- tlen = tlen + 1;
- nc = fgetc(fin);
-
- if (nc != '\'') {
- die("expected '");
- }
-
- token[tlen] = 0;
- nc = fgetc(fin);
-}
-
-// Read a hex number
-void
-feed_hex(void)
-{
- tt = T_HEX;
-
- tlen = 0;
- while (1) {
- if (!((nc >= '0' && nc <= '9')
- || (nc >= 'a' && nc <= 'f')
- || (nc >= 'A' && nc <= 'F'))) {
- break;
- }
- if (tlen == sizeof(token) - 1) {
- die("identifier too long");
- }
- token[tlen] = nc;
- tlen = tlen + 1;
- nc = fgetc(fin);
- }
-
- if (!tlen) {
- die("expected hex");
- }
-
- token[tlen] = 0;
-}
-
-// Read in a number
-void
-feed_num(void)
-{
- tt = T_NUM;
-
- if (nc == '0') {
- token[tlen] = nc;
- tlen = tlen + 1;
- nc = fgetc(fin);
-
- if (nc == 'x') {
- nc = fgetc(fin);
- feed_hex();
- return;
- }
- }
-
- while (1) {
- if (!(nc >= '0' && nc <= '9')) {
- break;
- }
- if (tlen == sizeof(token) - 1) {
- die("identifier too long");
- }
- token[tlen] = nc;
- tlen = tlen + 1;
- nc = fgetc(fin);
- }
- token[tlen] = 0;
-}
-
-// Read in the next token
-void
-feed(void)
-{
- tlen = 0;
-
- // Loop invariant: possible whitespace or EOF
- while (1) {
- if (nc == EOF) {
- // Reached the end of input
- tt = T_EOF;
- return;
- } else if (nc == ' ' || nc == '\t' || nc == '\r') {
- // Whitespace
- nc = fgetc(fin);
- } else if (nc == '\n') {
- // Line end
- nc = fgetc(fin);
- lineno = lineno + 1;
- } else if (nc == '/') {
- // Comment
- nc = fgetc(fin);
- if (nc == '/') {
- // Read until the end of the comment
- while (1) {
- if (nc == '\n' || nc == EOF) {
- break;
- }
- nc = fgetc(fin);
- }
- } else {
- tt = T_DIV;
- return;
- }
- } else {
- // Start of a real token
- break;
- }
- }
-
- // Identifier
- if ((nc >= 'a' && nc <= 'z') || (nc >= 'A' && nc <= 'Z') || nc == '_') {
- feed_ident();
- return;
- }
-
- // String
- if (nc == '"') {
- feed_str();
- return;
- }
-
- // Character
- if (nc == '\'') {
- feed_char();
- return;
- }
-
- // Number
- if (nc >= '0' && nc <= '9') {
- feed_num();
- return;
- }
-
- // Single character tokens
- if (nc == '(') {
- tt = T_LPAR;
- nc = fgetc(fin);
- } else if (nc == ')') {
- tt = T_RPAR;
- nc = fgetc(fin);
- } else if (nc == '{') {
- tt = T_LBRA;
- nc = fgetc(fin);
- } else if (nc == '}') {
- tt = T_RBRA;
- nc = fgetc(fin);
- } else if (nc == ',') {
- tt = T_COMMA;
- nc = fgetc(fin);
- } else if (nc == ';') {
- tt = T_SEMI;
- nc = fgetc(fin);
- } else if (nc == ':') {
- tt = T_COLON;
- nc = fgetc(fin);
- } else if (nc == '*') {
- tt = T_STAR;
- nc = fgetc(fin);
- } else if (nc == '.') {
- tt = T_DOT;
- nc = fgetc(fin);
- } else if (nc == '=') {
- tt = T_ASSIGN;
- nc = fgetc(fin);
- if (nc == '=') {
- tt = T_EQ;
- nc = fgetc(fin);
- }
- } else if (nc == '&') {
- tt = T_AMP;
- nc = fgetc(fin);
- if (nc == '&') {
- tt = T_BAND;
- nc = fgetc(fin);
- }
- } else if (nc == '~') {
- tt = T_NOT;
- nc = fgetc(fin);
- } else if (nc == '|') {
- tt = T_OR;
- nc = fgetc(fin);
- if (nc == '|') {
- tt = T_BOR;
- nc = fgetc(fin);
- }
- } else if (nc == '^') {
- tt = T_XOR;
- nc = fgetc(fin);
- } else if (nc == '!') {
- tt = T_BANG;
- nc = fgetc(fin);
- if (nc == '=') {
- tt = T_NE;
- nc = fgetc(fin);
- }
- } else if (nc == '<') {
- tt = T_LT;
- nc = fgetc(fin);
- if (nc == '<') {
- tt = T_LSH;
- nc = fgetc(fin);
- } else if (nc == '=') {
- tt = T_LE;
- nc = fgetc(fin);
- }
- } else if (nc == '>') {
- tt = T_GT;
- nc = fgetc(fin);
- if (nc == '>') {
- tt = T_RSH;
- nc = fgetc(fin);
- } else if (nc == '=') {
- tt = T_GE;
- nc = fgetc(fin);
- }
- } else if (nc == '[') {
- tt = T_LSQ;
- nc = fgetc(fin);
- } else if (nc == ']') {
- tt = T_RSQ;
- nc = fgetc(fin);
- } else if (nc == '+') {
- tt = T_ADD;
- nc = fgetc(fin);
- } else if (nc == '-') {
- tt = T_SUB;
- nc = fgetc(fin);
- } else if (nc == '%') {
- tt = T_MOD;
- nc = fgetc(fin);
- } else {
- die("invalid char");
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Grammar //
-///////////////////////////////////////////////////////////////////////////////
-
-struct node {
- int kind;
- struct node *a;
- struct node *b;
- struct type *t;
- int n;
- unsigned char *s;
- int offset;
- unsigned char *filename;
- int lineno;
-};
-
-enum {
- N_IDENT,
- N_NUM,
- N_CHAR,
- N_STR,
- N_STMTLIST,
- N_EXPRLIST,
- N_CALL,
- N_DOT,
- N_ARGLIST,
- N_FUNC,
- N_ARGDECL,
- N_FUNCDECL,
- N_PROGRAM,
- N_FUNCTYPE,
- N_PTRTYPE,
- N_STRUCT,
- N_MEMBERDECL,
- N_MEMBERLIST,
- N_CONDLIST,
- N_COND,
- N_ENUM,
- N_ENUMITEM,
- N_ENUMLIST,
- N_LOOP,
- N_BREAK,
- N_CONTINUE,
- N_RETURN,
- N_VARDECL,
- N_ASSIGN,
- N_SIZEOF,
- N_REF,
- N_DEREF,
- N_CAST,
- N_INDEX,
- N_LT,
- N_GT,
- N_LE,
- N_GE,
- N_EQ,
- N_NE,
- N_ADD,
- N_SUB,
- N_MUL,
- N_LSH,
- N_RSH,
- N_BNOT,
- N_BOR,
- N_BAND,
- N_AND,
- N_OR,
- N_XOR,
- N_NOT,
- N_POS,
- N_NEG,
- N_DIV,
- N_MOD,
-};
-
-// Construct a node
-struct node *
-mknode(int kind, struct node *a, struct node *b)
-{
- struct node *n;
-
- n = malloc(sizeof(*n));
- if (!n) {
- die("out of memory");
- }
-
- n->kind = kind;
- n->a = a;
- n->b = b;
- n->t = 0;
- n->n = 0;
- n->s = 0;
- n->offset = 0;
- n->filename = filename;
- n->lineno = lineno;
-
- return n;
-}
-
-// Copy the current token
-unsigned char *
-intern(void)
-{
- unsigned char *ret;
- int i;
-
- ret = malloc(tlen + 1);
- if (!ret) {
- return 0;
- }
-
- i = 0;
- while (1) {
- if (i >= tlen) {
- break;
- }
- ret[i] = token[i];
- i = i + 1;
- }
- ret[i] = 0;
-
- return ret;
-}
-
-// ident := IDENT
-struct node *
-ident(void)
-{
- struct node *n;
-
- if (tt != T_IDENT) {
- return 0;
- }
-
- n = mknode(N_IDENT, 0, 0);
- n->s = intern();
- feed();
-
- return n;
-}
-
-struct node *
-hex(void)
-{
- struct node *n;
- long x;
- int i;
- int d;
-
- x = 0;
- i = 0;
- while (1) {
- if (i >= tlen) {
- break;
- }
-
- d = token[i];
-
- if (d >= '0' && d <= '9') {
- d = d - '0';
- } else if (d >= 'a' && d <= 'f') {
- d = d - 'a' + 10;
- } else {
- d = d - 'A' + 10;
- }
-
- x = x * 16;
- x = x + d;
- i = i + 1;
-
- if (x > 0x7fffffff) {
- die("overflow");
- }
- }
-
- n = mknode(N_NUM, 0, 0);
- n->n = x;
- feed();
-
- return n;
-}
-
-// num := NUM
-struct node *
-num(void)
-{
- struct node *n;
- long x;
- int d;
- int i;
-
- if (tt == T_HEX) {
- return hex();
- }
-
- if (tt != T_NUM) {
- return 0;
- }
-
- x = 0;
- i = 0;
- while (1) {
- if (i >= tlen) {
- break;
- }
-
- d = token[i] - '0';
-
- x = x * 10;
-
- x = x + d;
- i = i + 1;
-
- if (x > 0x7fffffff) {
- die("overflow");
- }
- }
-
- n = mknode(N_NUM, 0, 0);
- n->n = x;
- feed();
-
- return n;
-}
-
-// chr := CHAR
-struct node *
-chr(void)
-{
- struct node *n;
-
- if (tt != T_CHAR) {
- return 0;
- }
-
- n = mknode(N_CHAR, 0, 0);
- n->n = token[0];
- feed();
-
- return n;
-}
-
-// str := STR
-struct node *
-str(void)
-{
- struct node *n;
-
- if (tt != T_STR) {
- return 0;
- }
-
- n = mknode(N_STR, 0, 0);
- n->s = intern();
- feed();
-
- return n;
-}
-
-// primary := ident
-// | num
-// | str
-// | chr
-// | '(' expr ')'
-struct node *
-primary(void)
-{
- struct node *n;
-
- n = ident();
- if (n) {
- return n;
- }
-
- n = num();
- if (n) {
- return n;
- }
-
- n = str();
- if (n) {
- return n;
- }
-
- n = chr();
- if (n) {
- return n;
- }
-
- if (tt == T_LPAR) {
- feed();
-
- n = expr();
- if (!n) {
- die("expected expr");
- }
-
- if (tt != T_RPAR) {
- die("expected )");
- }
- feed();
-
- return n;
- }
-
- return 0;
-}
-
-// expr_list := expr
-// | expr ',' expr_list
-struct node *
-expr_list(void)
-{
- struct node *n;
- struct node *e;
- struct node *a;
-
- a = expr();
- if (!a) {
- return 0;
- }
-
- e = mknode(N_EXPRLIST, a, 0);
- n = e;
-
- while (1) {
- if (tt != T_COMMA) {
- return n;
- }
- feed();
-
- a = expr();
- if (!a) {
- die("expected expr");
- }
-
- e->b = mknode(N_EXPRLIST, a, 0);
- e = e->b;
- }
-}
-
-// post_expr := primary
-// | 'sizeof' '(' expr ')'
-// | post_expr '[' expr ']'
-// | post_expr '(' expr_list ')'
-// | post_expr '.' ident
-// | post_expr ':' type
-struct node *
-post_expr(void)
-{
- struct node *n;
- struct node *b;
-
- if (tt == T_IDENT && !cmp(token, (unsigned char *)"sizeof")) {
- feed();
-
- if (tt != T_LPAR) {
- die("expected (");
- }
- feed();
-
- n = expr();
- if (!n) {
- die("expected expr");
- }
-
- if (tt != T_RPAR) {
- die("expected )");
- }
- feed();
-
- return mknode(N_SIZEOF, n, 0);;
- }
-
- n = primary();
- if (!n) {
- return 0;
- }
-
- while (1) {
- if (tt == T_LSQ) {
- feed();
-
- b = expr();
-
- if (tt != T_RSQ) {
- die("expected ]");
- }
- feed();
-
- n = mknode(N_INDEX, n, b);
- } else if (tt == T_LPAR) {
- feed();
-
- b = expr_list();
-
- if (tt != T_RPAR) {
- die("expected )");
- }
- feed();
-
- n = mknode(N_CALL, n, b);
- } else if (tt == T_DOT) {
- feed();
-
- b = ident();
- if (!b) {
- die("expected ident");
- }
-
- n = mknode(N_DOT, n, b);
- } else if (tt == T_COLON) {
- feed();
-
- b = type();
- if (!b) {
- die("expected type");
- }
-
- n = mknode(N_CAST, n, b);
- } else {
- return n;
- }
- }
-}
-
-// unary_expr := post_expr
-// | '&' unary_expr
-// | '*' unary_expr
-// | '+' unary_expr
-// | '-' unary_expr
-// | '~' unary_expr
-// | '!' unary_expr
-struct node *
-unary_expr(void)
-{
- struct node *n;
-
- if (tt == T_AMP) {
- feed();
-
- n = unary_expr();
- if (!n) {
- die("expected unary_expr");
- }
-
- return mknode(N_REF, n, 0);
- }
-
- if (tt == T_STAR) {
- feed();
-
- n = unary_expr();
- if (!n) {
- die("expected unary_expr");
- }
-
- return mknode(N_DEREF, n, 0);
- }
-
- if (tt == T_ADD) {
- feed();
-
- n = unary_expr();
- if (!n) {
- die("expected unary_expr");
- }
-
- return mknode(N_POS, n, 0);
- }
-
- if (tt == T_SUB) {
- feed();
-
- n = unary_expr();
- if (!n) {
- die("expected unary_expr");
- }
-
- return mknode(N_NEG, n, 0);
- }
-
- if (tt == T_NOT) {
- feed();
-
- n = unary_expr();
- if (!n) {
- die("expected unary_expr");
- }
-
- return mknode(N_NOT, n, 0);
- }
-
- if (tt == T_BANG) {
- feed();
-
- n = unary_expr();
- if (!n) {
- die("expected unary_expr");
- }
-
- return mknode(N_BNOT, n, 0);
- }
-
- return post_expr();
-}
-
-
-// shift_expr := unary_expr
-// | shift_expr '<<' unary_expr
-// | shift_expr '>>' unary_expr
-struct node *
-shift_expr(void)
-{
- struct node *a;
- struct node *b;
-
- a = unary_expr();
- if (!a) {
- return 0;
- }
-
- while (1) {
- if (tt == T_LSH) {
- feed();
-
- b = unary_expr();
- if (!b) {
- die("expected unary_expr");
- }
-
- a = mknode(N_LSH, a, b);
- } else if (tt == T_RSH) {
- feed();
-
- b = unary_expr();
- if (!b) {
- die("expected unary_expr");
- }
-
- a = mknode(N_RSH, a, b);
- } else {
- return a;
- }
- }
-}
-
-// mul_expr := shift_expr
-// | mul_expr '*' shift_expr
-// | mul_expr '/' shift_expr
-// | mul_expr '%' shift_expr
-// | mul_expr '&' shift_expr
-struct node *
-mul_expr(void)
-{
- struct node *a;
- struct node *b;
-
- a = shift_expr();
- if (!a) {
- return 0;
- }
-
- while (1) {
- if (tt == T_STAR) {
- feed();
-
- b = shift_expr();
- if (!b) {
- die("expected shift_expr");
- }
-
- a = mknode(N_MUL, a, b);
- } else if (tt == T_DIV) {
- feed();
-
- b = shift_expr();
- if (!b) {
- die("expected shift_expr");
- }
-
- a = mknode(N_DIV, a, b);
- } else if (tt == T_MOD) {
- feed();
-
- b = shift_expr();
- if (!b) {
- die("expected shift_expr");
- }
-
- a = mknode(N_MOD, a, b);
- } else if (tt == T_AMP) {
- feed();
-
- b = shift_expr();
- if (!b) {
- die("expected shift_expr");
- }
-
- a = mknode(N_AND, a, b);
- } else {
- return a;
- }
- }
-}
-
-// add_expr := mul_expr
-// | add_expr '+' mul_expr
-// | add_expr '-' mul_expr
-// | add_expr '|' mul_expr
-// | add_expr '^' mul_expr
-struct node *
-add_expr(void)
-{
- struct node *a;
- struct node *b;
-
- a = mul_expr();
- if (!a) {
- return 0;
- }
-
- while (1) {
- if (tt == T_ADD) {
- feed();
-
- b = mul_expr();
- if (!b) {
- die("expected mul_expr");
- }
-
- a = mknode(N_ADD, a, b);
- } else if (tt == T_SUB) {
- feed();
-
- b = mul_expr();
- if (!b) {
- die("expected mul_expr");
- }
-
- a = mknode(N_SUB, a, b);
- } else if (tt == T_OR) {
- feed();
-
- b = mul_expr();
- if (!b) {
- die("expected mul_expr");
- }
-
- a = mknode(N_OR, a, b);
- } else if (tt == T_XOR) {
- feed();
-
- b = mul_expr();
- if (!b) {
- die("expected mul_expr");
- }
-
- a = mknode(N_XOR, a, b);
- } else {
- return a;
- }
- }
-}
-
-// comp_expr := add_expr
-// | add_expr '<' add_expr
-// | add_expr '>' add_expr
-// | add_expr '<=' add_expr
-// | add_expr '>=' add_expr
-// | add_expr '==' add_expr
-// | add_expr '!=' add_expr
-struct node *
-comp_expr(void)
-{
- struct node *a;
- struct node *b;
-
- a = add_expr();
- if (!a) {
- return 0;
- }
-
- if (tt == T_LT) {
- feed();
-
- b = add_expr();
- if (!b) {
- die("expected add_expr");
- }
-
- return mknode(N_LT, a, b);
- }
-
- if (tt == T_GT) {
- feed();
-
- b = add_expr();
- if (!b) {
- die("expected add_expr");
- }
-
- return mknode(N_GT, a, b);
- }
-
- if (tt == T_LE) {
- feed();
-
- b = add_expr();
- if (!b) {
- die("expected add_expr");
- }
-
- return mknode(N_LE, a, b);
- }
-
- if (tt == T_GE) {
- feed();
-
- b = add_expr();
- if (!b) {
- die("expected add_expr");
- }
-
- return mknode(N_GE, a, b);
- }
-
- if (tt == T_EQ) {
- feed();
-
- b = add_expr();
- if (!b) {
- die("expected add_expr");
- }
-
- return mknode(N_EQ, a, b);
- }
-
- if (tt == T_NE) {
- feed();
-
- b = add_expr();
- if (!b) {
- die("expected add_expr");
- }
-
- return mknode(N_NE, a, b);
- }
-
- return a;
-}
-
-// bool_expr := bool_expr
-// | comp_expr '&&' bool_expr
-// | comp_expr '||' bool_expr
-struct node *
-bool_expr(void)
-{
- struct node *a;
- struct node *b;
-
- a = comp_expr();
- if (!a) {
- return 0;
- }
-
- if (tt == T_BAND) {
- feed();
-
- b = bool_expr();
- if (!b) {
- die("expected bool_expr");
- }
-
- return mknode(N_BAND, a, b);
- }
-
- if (tt == T_BOR) {
- feed();
-
- b = bool_expr();
- if (!b) {
- die("expected bool_expr");
- }
-
- return mknode(N_BOR, a, b);
- }
-
- return a;
-}
-
-// expr := bool_expr
-// | bool_expr '=' expr
-struct node *
-expr(void)
-{
- struct node *a;
- struct node *b;
-
- a = bool_expr();
- if (!a) {
- return 0;
- }
-
- if (tt == T_ASSIGN) {
- feed();
-
- b = expr();
- if (!b) {
- die("expected expr");
- }
-
- return mknode(N_ASSIGN, a, b);
- }
-
- return a;
-}
-
-// if_stmt := 'if' expr '{' stmt_list '}'
-// | 'if' expr '{' stmt_list '}' 'else' if_stmt
-// | 'if' expr '{' stmt_list '}' 'else' '{' stmt_list '}'
-struct node *
-if_stmt(void)
-{
- struct node *n;
- struct node *e;
- struct node *a;
- struct node *b;
-
- if (tt != T_IDENT || cmp(token, (unsigned char *)"if")) {
- return 0;
- }
- feed();
-
- n = mknode(N_CONDLIST, 0, 0);
- e = n;
-
- while (1) {
- a = expr();
- if (!a) {
- die("expected expr");
- }
-
- if (tt != T_LBRA) {
- die("expected {");
- }
- feed();
-
- b = stmt_list();
-
- if (tt != T_RBRA) {
- die("expected }");
- }
- feed();
-
- e->a = mknode(N_COND, a, b);
-
- if (tt != T_IDENT || cmp(token, (unsigned char *)"else")) {
- return n;
- }
- feed();
-
- if (tt == T_LBRA) {
- feed();
-
- b = stmt_list();
-
- if (tt != T_RBRA) {
- die("expected }");
- }
- feed();
-
- e->b = mknode(N_CONDLIST, mknode(N_COND, 0, b), 0);
-
- return n;
- }
-
- if (tt != T_IDENT || cmp(token, (unsigned char *)"if")) {
- die("expected if");
- }
- feed();
-
- e->b = mknode(N_CONDLIST, 0, 0);
- e = e->b;
- }
-}
-
-// loop_stmt := 'loop' '{' stmt_list '}'
-struct node *
-loop_stmt(void)
-{
- struct node *a;
-
- if (tt != T_IDENT || cmp(token, (unsigned char *)"loop")) {
- return 0;
- }
- feed();
-
- if (tt != T_LBRA) {
- die("expected {");
- }
- feed();
-
- a = stmt_list();
-
- if (tt != T_RBRA) {
- die("expected }");
- }
- feed();
-
- return mknode(N_LOOP, a, 0);
-}
-
-// break_stmt := 'break'
-struct node *
-break_stmt(void)
-{
- if (tt != T_IDENT || cmp(token, (unsigned char *)"break")) {
- return 0;
- }
- feed();
-
- return mknode(N_BREAK, 0, 0);
-}
-
-// continue_stmt := 'continue'
-struct node *
-continue_stmt(void)
-{
- if (tt != T_IDENT || cmp(token, (unsigned char *)"continue")) {
- return 0;
- }
- feed();
-
- return mknode(N_CONTINUE, 0, 0);
-}
-
-// return_stmt := 'return'
-// | 'return' expr
-struct node *
-return_stmt(void)
-{
- struct node *a;
-
- if (tt != T_IDENT || cmp(token, (unsigned char *)"return")) {
- return 0;
- }
- feed();
-
- a = expr();
-
- return mknode(N_RETURN, a, 0);
-}
-
-// var_decl := ident ':' type
-struct node *
-var_decl(void)
-{
- struct node *n;
- struct node *a;
- struct node *b;
-
- a = ident();
- if (!a) {
- return 0;
- }
-
- if (tt != T_COLON) {
- die("expected :");
- }
- feed();
-
- b = type();
- if (!b) {
- die("expected type");
- }
-
- return mknode(N_VARDECL, a, b);
-}
-
-// var_stmt := 'var' var_decl
-struct node *
-var_stmt(void)
-{
- struct node *a;
-
- if (tt != T_IDENT || cmp(token, (unsigned char *)"var")) {
- return 0;
- }
- feed();
-
- a = var_decl();
- if (!a) {
- die("expected var_decl");
- }
-
- return a;
-}
-
-// stmt := if_stmt
-// | loop_stmt
-// | break_stmt ';'
-// | continue_stmt ';'
-// | return_stmt ';'
-// | var_stmt ';'
-// | expr ';'
-struct node *
-stmt(void)
-{
- struct node *n;
-
- n = if_stmt();
- if (n) {
- return n;
- }
-
- n = loop_stmt();
- if (n) {
- return n;
- }
-
- n = break_stmt();
- if (n) {
- if (tt != T_SEMI) {
- die("expected ;");
- }
- feed();
-
- return n;
- }
-
- n = return_stmt();
- if (n) {
- if (tt != T_SEMI) {
- die("expected ;");
- }
- feed();
-
- return n;
- }
-
- n = continue_stmt();
- if (n) {
- if (tt != T_SEMI) {
- die("expected ;");
- }
- feed();
-
- return n;
- }
-
- n = var_stmt();
- if (n) {
- if (tt != T_SEMI) {
- die("expected ;");
- }
- feed();
-
- return n;
- }
-
- n = expr();
- if (n) {
- if (tt != T_SEMI) {
- die("expected ;");
- }
- feed();
-
- return n;
- }
-
- return 0;
-}
-
-// stmt_list := stmt
-// | stmt stmt_list
-struct node *
-stmt_list(void)
-{
- struct node *n;
- struct node *e;
- struct node *a;
-
- a = stmt();
- if (!a) {
- return 0;
- }
-
- e = mknode(N_STMTLIST, a, 0);
- n = e;
-
- while (1) {
- a = stmt();
- if (!a) {
- return n;
- }
-
- e->b = mknode(N_STMTLIST, a, 0);
- e = e->b;
- }
-}
-
-// type := ident
-// | '*' type
-// | '(' type ')'
-struct node *
-type(void)
-{
- struct node *n;
-
- if (tt == T_STAR) {
- feed();
-
- n = type();
-
- return mknode(N_PTRTYPE, n, 0);
- }
-
- if (tt == T_LPAR) {
- feed();
-
- n = type();
-
- if (tt != T_RPAR) {
- die("expected )");
- }
- feed();
-
- return n;
- }
-
- return ident();
-}
-
-// arg_decl := ':' type
-// ident ':' type
-struct node *
-arg_decl(void)
-{
- struct node *n;
- struct node *a;
- struct node *b;
-
- a = ident();
- if (!a) {
- return 0;
- }
-
- if (tt != T_COLON) {
- die("expected :");
- }
- feed();
-
- b = type();
- if (!b) {
- die("expected type");
- }
-
- return mknode(N_ARGDECL, a, b);
-}
-
-// arg_list := arg_decl
-// | arg_decl ',' arg_list
-struct node *
-arg_list(void)
-{
- struct node *n;
- struct node *e;
- struct node *a;
-
- a = arg_decl();
- if (!a) {
- return 0;
- }
-
- e = mknode(N_ARGLIST, a, 0);
- n = e;
-
- while (1) {
- if (tt != T_COMMA) {
- return n;
- }
- feed();
-
- a = arg_decl();
- if (!a) {
- die("expected identifier");
- }
-
- e->b = mknode(N_ARGLIST, a, 0);
- e = e->b;
- }
-}
-
-// func_decl := ident '(' ')' ':' type
-// | ident '(' arg_list ')' ':' type
-// | ident '(' ')'
-// | ident '(' arg_list ')'
-struct node *
-func_decl(void)
-{
- struct node *a;
- struct node *b;
- struct node *c;
-
- a = ident();
- if (!a) {
- return 0;
- }
-
- if (tt != T_LPAR) {
- die("expected (");
- }
- feed();
-
- b = arg_list();
-
- if (tt != T_RPAR) {
- die("expected )");
- }
- feed();
-
- if (tt != T_COLON) {
- return mknode(N_FUNCDECL, a, mknode(N_FUNCTYPE, b, 0));
- }
- feed();
-
- c = type();
- if (!c) {
- die("expected type");
- }
-
- return mknode(N_FUNCDECL, a, mknode(N_FUNCTYPE, b, c));
-}
-
-
-// func := func_decl '{' stmt_list '}'
-// | func_decl ';'
-struct node *
-func(void)
-{
- struct node *n;
- struct node *a;
- struct node *b;
-
- a = func_decl();
- if (!a) {
- return 0;
- }
-
- if (tt == T_SEMI) {
- feed();
- return a;
- }
-
- if (tt != T_LBRA) {
- die("expected {");
- }
- feed();
-
- b = stmt_list();
-
- if (tt != T_RBRA) {
- die("expected }");
- }
- feed();
-
- return mknode(N_FUNC, a, b);
-}
-
-// member_decl := ident ':' type
-struct node *
-member_decl(void)
-{
- struct node *n;
- struct node *a;
- struct node *b;
-
- a = ident();
- if (!a) {
- return 0;
- }
-
- if (tt != T_COLON) {
- die("expected :");
- }
- feed();
-
- b = type();
- if (!b) {
- die("expected type");
- }
-
- return mknode(N_MEMBERDECL, a, b);
-}
-
-// enum_item := ident
-// | ident '=' num
-struct node *
-enum_item(void)
-{
- struct node *a;
- struct node *b;
-
- a = ident();
- if (!a) {
- return 0;
- }
-
- if (tt != T_ASSIGN) {
- return mknode(N_ENUMITEM, a, 0);
- }
- feed();
-
- b = num();
- if (!b) {
- die("expected num");
- }
-
- return mknode(N_ENUMITEM, a, b);
-}
-
-// enum_list := enum_item
-// | enum_list ',' enum_list
-struct node *
-enum_list(void)
-{
- struct node *n;
- struct node *e;
- struct node *a;
-
- a = enum_item();
- if (!a) {
- return 0;
- }
-
- e = mknode(N_ENUMLIST, a, 0);
- n = e;
-
- while (1) {
- if (tt != T_COMMA) {
- return n;
- }
- feed();
-
- a = enum_item();
- if (!a) {
- return n;
- }
-
- e->b = mknode(N_ENUMLIST, a, 0);
- e = e->b;
- }
-}
-
-// enum_decl := 'enum' ident '{' enum_list '}'
-struct node *
-enum_decl(void)
-{
- struct node *b;
-
- if (tt != T_IDENT) {
- return 0;
- }
-
- if (cmp(token, (unsigned char *)"enum")) {
- return 0;
- }
- feed();
-
- if (tt != T_LBRA) {
- die("expected {");
- }
- feed();
-
- b = enum_list();
-
- if (tt != T_RBRA) {
- die("expected }");
- }
- feed();
-
- return mknode(N_ENUM, 0, b);
-}
-
-// member_list := member_decl
-// | member_decl ';' member_list
-struct node *
-member_list(void)
-{
- struct node *n;
- struct node *e;
- struct node *a;
-
- a = member_decl();
- if (!a) {
- return 0;
- }
-
- e = mknode(N_MEMBERLIST, a, 0);
- n = e;
-
- while (1) {
- if (tt != T_SEMI) {
- return n;
- }
- feed();
-
- a = member_decl();
- if (!a) {
- return n;
- }
-
- e->b = mknode(N_MEMBERLIST, a, 0);
- e = e->b;
- }
-}
-
-// struct_decl := 'struct' ident '{' member_list '}'
-struct node *
-struct_decl(void)
-{
- struct node *a;
- struct node *b;
-
- if (tt != T_IDENT) {
- return 0;
- }
-
- if (cmp(token, (unsigned char *)"struct")) {
- return 0;
- }
- feed();
-
- a = ident();
- if (!a) {
- die("expected ident");
- }
-
- if (tt != T_LBRA) {
- die("expected {");
- }
- feed();
-
- b = member_list();
-
- if (tt != T_RBRA) {
- die("expected }");
- }
- feed();
-
- return mknode(N_STRUCT, a, b);
-}
-
-// decl := func
-// | struct_decl
-struct node *
-decl(void)
-{
- struct node *n;
-
- n = enum_decl();
- if (n) {
- return n;
- }
-
- n = struct_decl();
- if (n) {
- return n;
- }
-
- return func();
-}
-
-// program := func
-// | func program
-struct node *
-program(struct node *p)
-{
- struct node *n;
- struct node *e;
- struct node *d;
-
- d = decl();
- if (!d) {
- return p;
- }
-
- e = mknode(N_PROGRAM, d, 0);
- n = e;
-
- while (1) {
- d = decl();
- if (!d) {
- if (tt != T_EOF) {
- die("expected eof");
- }
-
- e->b = p;
- return n;
- }
-
- e->b = mknode(N_PROGRAM, d, 0);
- e = e->b;
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Setup //
-///////////////////////////////////////////////////////////////////////////////
-
-// Prime the parser by reading in the lookahead
-void
-setup(void)
-{
- filename = (unsigned char *)"<stdin>";
- fin = stdin;
- fout = stdout;
- lineno = 1;
- nc = 0;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Type System //
-///////////////////////////////////////////////////////////////////////////////
-
-enum {
- TY_VOID,
- TY_INT,
- TY_BYTE,
- TY_PTR,
- TY_ARG,
- TY_FUNC,
- TY_STRUCT,
-};
-
-struct type {
- int kind;
- struct sdecl *s;
- struct type *val;
- struct type *arg;
-};
-
-struct decl {
- unsigned char *name;
- struct decl *p;
- struct decl *l;
- struct decl *r;
- struct type *ftype;
- struct node *args;
- struct node *body;
- struct label *label;
- struct vdecl *locals;
- struct vdecl *vlocals;
- struct vdecl *vargs;
- int preamble;
- int defined;
-};
-
-struct vdecl {
- unsigned char *name;
- struct vdecl *p;
- struct vdecl *l;
- struct vdecl *r;
- struct vdecl *next;
- struct type *t;
- int size;
- int offset;
- int defined;
-};
-
-struct mdecl {
- unsigned char *name;
- struct mdecl *p;
- struct mdecl *l;
- struct mdecl *r;
- struct mdecl *next;
- struct type *t;
- int offset;
- int defined;
-};
-
-struct sdecl {
- unsigned char *name;
- struct sdecl *p;
- struct sdecl *l;
- struct sdecl *r;
- struct mdecl *mem;
- struct mdecl *vmem;
- struct mdecl *vmem_last;
- int size;
- int computed;
- int defined;
-};
-
-struct edecl {
- unsigned char *name;
- struct edecl *p;
- struct edecl *l;
- struct edecl *r;
- int val;
- int defined;
-};
-
-struct decl *decls;
-struct sdecl *structs;
-struct edecl *enums;
-
-// Unify two types
-void
-unify(struct type *a, struct type *b)
-{
- int kind;
-
- if (!a || !b || a == b) {
- return;
- }
-
- if (a->kind != b->kind) {
- die("type error");
- }
-
- kind = a->kind;
- if (kind == TY_PTR) {
- unify(a->val, b->val);
- } else if (kind == TY_FUNC) {
- unify(a->val, b->val);
- unify(a->arg, b->arg);
- } else if (kind == TY_ARG) {
- unify(a->val, b->val);
- unify(a->arg, b->arg);
- } else if (kind == TY_STRUCT) {
- if (a->s != b->s) {
- die("type error");
- }
- } else if (kind != TY_VOID && kind != TY_INT && kind != TY_BYTE) {
- die("unify: invalid type");
- }
-}
-
-// Find a function declaration by name
-struct decl *
-find(unsigned char *name)
-{
- struct decl **link;
- struct decl *d;
- struct decl *p;
- int c;
-
- p = 0;
- link = &decls;
- while (1) {
- d = *link;
- if (!d) {
- break;
- }
-
- c = cmp(name, d->name);
-
- if (c < 0) {
- p = d;
- link = &d->l;
- } else if (c > 0) {
- p = d;
- link = &d->r;
- } else {
- return d;
- }
- }
-
- d = malloc(sizeof(*d));
- if (!d) {
- die("out of memory");
- }
-
- d->name = name;
- d->ftype = 0;
- d->args = 0;
- d->body = 0;
- d->p = p;
- d->l = 0;
- d->r = 0;
- d->label = mklabel();
- d->locals = 0;
- d->vlocals = 0;
- d->vargs = 0;
- d->preamble = 0;
- d->defined = 0;
-
- *link = d;
-
- return d;
-}
-
-// Find a local by name
-struct vdecl *
-vfind(struct decl *f, unsigned char *name, int def)
-{
- struct vdecl **link;
- struct vdecl *d;
- struct vdecl *p;
- int c;
-
- p = 0;
- link = &f->locals;
- while (1) {
- d = *link;
- if (!d) {
- break;
- }
-
- c = cmp(name, d->name);
-
- if (c < 0) {
- p = d;
- link = &d->l;
- } else if (c > 0) {
- p = d;
- link = &d->r;
- } else {
- return d;
- }
- }
-
- if (!def) {
- return 0;
- }
-
- d = malloc(sizeof(*d));
- if (!d) {
- die("out of memory");
- }
-
- d->name = name;
- d->p = p;
- d->l = 0;
- d->r = 0;
- d->t = 0;
- d->next = 0;
- d->size = 0;
- d->offset = 0;
- d->defined = 0;
-
- *link = d;
-
- return d;
-}
-
-// Find a member by name
-struct mdecl *
-mfind(struct sdecl *s, unsigned char *name)
-{
- struct mdecl **link;
- struct mdecl *d;
- struct mdecl *p;
- int c;
-
- p = 0;
- link = &s->mem;
- while (1) {
- d = *link;
- if (!d) {
- break;
- }
-
- c = cmp(name, d->name);
-
- if (c < 0) {
- p = d;
- link = &d->l;
- } else if (c > 0) {
- p = d;
- link = &d->r;
- } else {
- return d;
- }
- }
-
- d = malloc(sizeof(*d));
- if (!d) {
- die("out of memory");
- }
-
- d->name = name;
- d->p = p;
- d->l = 0;
- d->r = 0;
- d->t = 0;
- d->next = 0;
- d->offset = 0;
- d->defined = 0;
-
- if (s->vmem_last) {
- s->vmem_last->next = d;
- } else {
- s->vmem = d;
- }
- s->vmem_last = d;
-
- *link = d;
-
- return d;
-}
-
-// Find a structure by name
-struct sdecl *
-sfind(unsigned char *name)
-{
- struct sdecl **link;
- struct sdecl *d;
- struct sdecl *p;
- int c;
-
- p = 0;
- link = &structs;
- while (1) {
- d = *link;
- if (!d) {
- break;
- }
-
- c = cmp(name, d->name);
-
- if (c < 0) {
- p = d;
- link = &d->l;
- } else if (c > 0) {
- p = d;
- link = &d->r;
- } else {
- return d;
- }
- }
-
- d = malloc(sizeof(*d));
- if (!d) {
- die("out of memory");
- }
-
- d->name = name;
- d->p = p;
- d->l = 0;
- d->r = 0;
- d->mem = 0;
- d->vmem_last = 0;
- d->vmem = 0;
- d->size = 0;
- d->computed = 0;
- d->defined = 0;
-
- *link = d;
-
- return d;
-}
-
-// Find a enum by name
-struct edecl *
-efind(unsigned char *name, int def)
-{
- struct edecl **link;
- struct edecl *d;
- struct edecl *p;
- int c;
-
- p = 0;
- link = &enums;
- while (1) {
- d = *link;
- if (!d) {
- break;
- }
-
- c = cmp(name, d->name);
-
- if (c < 0) {
- p = d;
- link = &d->l;
- } else if (c > 0) {
- p = d;
- link = &d->r;
- } else {
- return d;
- }
- }
-
- if (!def) {
- return 0;
- }
-
- d = malloc(sizeof(*d));
- if (!d) {
- die("out of memory");
- }
-
- d->name = name;
- d->p = p;
- d->l = 0;
- d->r = 0;
- d->val = 0;
- d->defined = 0;
-
- *link = d;
-
- return d;
-}
-
-struct type *
-mktype(int kind, struct type *val, struct type *arg, struct sdecl *s)
-{
- struct type *t;
-
- t = malloc(sizeof(*t));
- if (!t) {
- die("out of memory");
- }
-
- t->s = s;
- t->kind = kind;
- t->val = val;
- t->arg = arg;
-
- return t;
-}
-
-// Convert a type node into a type
-struct type *
-prototype(struct node *n)
-{
- struct type *a;
- struct type *b;
- struct sdecl *s;
- int kind;
-
- if (!n) {
- return 0;
- }
-
- kind = n->kind;
- if (kind == N_IDENT) {
- if (!cmp(n->s, (unsigned char *)"void")) {
- return mktype(TY_VOID, 0, 0, 0);
- }
- if (!cmp(n->s, (unsigned char *)"int")) {
- return mktype(TY_INT, 0, 0, 0);
- }
- if (!cmp(n->s, (unsigned char *)"byte")) {
- return mktype(TY_BYTE, 0, 0, 0);
- }
-
- s = sfind(n->s);
-
- return mktype(TY_STRUCT, 0, 0, s);
- } else if (kind == N_ARGLIST) {
- a = prototype(n->a->b);
- b = prototype(n->b);
-
- kind = a->kind;
- if (kind != TY_INT && kind != TY_BYTE
- && kind != TY_PTR && kind != TY_FUNC) {
- die("not a ptr arg");
- }
-
- return mktype(TY_ARG, a, b, 0);
- } else if (kind == N_FUNCTYPE) {
- if (n->b) {
- a = prototype(n->b);
- } else {
- a = mktype(TY_VOID, 0, 0, 0);
- }
-
- b = prototype(n->a);
-
- kind = a->kind;
- if (kind != TY_VOID && kind != TY_INT && kind != TY_BYTE
- && kind != TY_PTR && kind != TY_FUNC) {
- die("not a ptr return");
- }
-
- return mktype(TY_FUNC, a, b, 0);
- } else if (kind == N_PTRTYPE) {
- return mktype(TY_PTR, prototype(n->a), 0, 0);
- } else {
- die("prototype: invalid type");
- return 0;
- }
-}
-
-// Evaluate function declaration
-struct decl *
-declare(struct node *n)
-{
- struct decl *d;
- struct type *t;
- d = find(n->a->s);
- t = prototype(n->b);
- filename = n->filename;
- lineno = n->lineno;
- if (d->ftype) {
- unify(d->ftype, t);
- } else {
- d->ftype = t;
- }
- return d;
-}
-
-// Function definition
-void
-define(struct node *n)
-{
- struct decl *d;
-
- d = declare(n->a);
-
- if (d->defined) {
- die("duplicate declaration");
- }
-
- d->body = n->b;
- d->defined = 1;
- d->args = n->a->b->a;
-}
-
-struct decl *curfunc;
-struct sdecl *curstruct;
-struct vdecl **link_arg;
-struct vdecl **link_local;
-
-int
-type_isint(struct type *t)
-{
- return t->kind == TY_INT || t->kind == TY_BYTE;
-}
-
-int
-type_isprim(struct type *t)
-{
- return t->kind != TY_VOID && t->kind != TY_STRUCT;
-}
-
-void
-typeexpr(struct node *n)
-{
- struct node *a;
- struct type *t;
- struct decl *d;
- struct vdecl *v;
- struct mdecl *m;
- struct edecl *e;
- int kind;
-
- kind = n->kind;
- if (kind == N_STR) {
- n->t = mktype(TY_PTR, mktype(TY_BYTE, 0, 0, 0), 0, 0);
- } else if (kind == N_NUM) {
- n->t = mktype(TY_INT, 0, 0, 0);
- } else if (kind == N_CHAR) {
- n->t = mktype(TY_INT, 0, 0, 0);
- } else if (kind == N_CALL) {
- typeexpr(n->a);
- t = n->a->t;
- if (t->kind != TY_FUNC) {
- die("calling not a function");
- }
- a = n->b;
- t = t->arg;
- while (1) {
- if (!a || !t) {
- break;
- }
- typeexpr(a->a);
- unify(a->a->t, t->val);
- a = a->b;
- t = t->arg;
- }
- if (a || t) {
- die("wrong number of arguments");
- }
- n->t = n->a->t->val;
- } else if (kind == N_DOT) {
- typeexpr(n->a);
- t = n->a->t;
- if (t->kind == TY_PTR) {
- t = t->val;
- }
- if (t->kind != TY_STRUCT) {
- die("dot not a struct");
- }
- m = mfind(t->s, n->b->s);
- if (!m->defined) {
- die("no such member");
- }
- n->t = m->t;
- n->offset = m->offset;
- } else if (kind == N_IDENT) {
- e = efind(n->s, 0);
- if (e) {
- n->t = mktype(TY_INT, 0, 0, 0);
- } else {
- v = vfind(curfunc, n->s, 0);
- if (v) {
- n->t = v->t;
- } else {
- d = find(n->s);
- if (!d->ftype) {
- die("no such variable");
- }
- n->t = d->ftype;
- }
- }
- } else if (kind == N_ASSIGN) {
- typeexpr(n->a);
- typeexpr(n->b);
- unify(n->a->t, n->b->t);
- t = n->a->t;
- n->t = t;
- if (t->kind != TY_INT && t->kind != TY_BYTE
- && t->kind != TY_PTR && t->kind != TY_FUNC) {
- die("assignment not primitive");
- }
- } else if (kind == N_SIZEOF) {
- typeexpr(n->a);
- n->t = mktype(TY_INT, 0, 0, 0);
- } else if (kind == N_REF) {
- typeexpr(n->a);
- t = n->a->t;
- n->t = mktype(TY_PTR, t, 0, 0);
- } else if (kind == N_DEREF) {
- typeexpr(n->a);
- t = n->a->t;
- if (t->kind != TY_PTR) {
- die("deref not a pointer");
- }
- t = t->val;
- n->t = t;
- } else if (kind == N_INDEX) {
- typeexpr(n->a);
- t = n->a->t;
- if (t->kind != TY_PTR) {
- die("not a pointer");
- }
- typeexpr(n->b);
- if (!type_isint(n->b->t)) {
- die("not an int");
- }
- n->t = t->val;
- n->offset = type_sizeof(t->val);
- if (t->val->kind == TY_BYTE) {
- n->offset = 1;
- }
- } else if (kind == N_LT) {
- typeexpr(n->a);
- if (!type_isprim(n->a->t)) {
- die("not an prim");
- }
- typeexpr(n->b);
- if (!type_isprim(n->b->t)) {
- die("not an prim");
- }
- unify(n->a->t, n->b->t);
- n->t = mktype(TY_INT, 0, 0, 0);
- } else if (kind == N_GT) {
- typeexpr(n->a);
- if (!type_isprim(n->a->t)) {
- die("not an prim");
- }
- typeexpr(n->b);
- if (!type_isprim(n->b->t)) {
- die("not an prim");
- }
- unify(n->a->t, n->b->t);
- n->t = mktype(TY_INT, 0, 0, 0);
- } else if (kind == N_LE) {
- typeexpr(n->a);
- if (!type_isprim(n->a->t)) {
- die("not an prim");
- }
- typeexpr(n->b);
- if (!type_isprim(n->b->t)) {
- die("not an prim");
- }
- unify(n->a->t, n->b->t);
- n->t = mktype(TY_INT, 0, 0, 0);
- } else if (kind == N_GE) {
- typeexpr(n->a);
- if (!type_isprim(n->a->t)) {
- die("not an prim");
- }
- typeexpr(n->b);
- if (!type_isprim(n->b->t)) {
- die("not an prim");
- }
- unify(n->a->t, n->b->t);
- n->t = mktype(TY_INT, 0, 0, 0);
- } else if (kind == N_EQ) {
- typeexpr(n->a);
- if (!type_isprim(n->a->t)) {
- die("not an prim");
- }
- typeexpr(n->b);
- if (!type_isprim(n->b->t)) {
- die("not an prim");
- }
- unify(n->a->t, n->b->t);
- n->t = mktype(TY_INT, 0, 0, 0);
- } else if (kind == N_NE) {
- typeexpr(n->a);
- if (!type_isprim(n->a->t)) {
- die("not an prim");
- }
- typeexpr(n->b);
- if (!type_isprim(n->b->t)) {
- die("not an prim");
- }
- unify(n->a->t, n->b->t);
- n->t = mktype(TY_INT, 0, 0, 0);
- } else if (kind == N_ADD) {
- typeexpr(n->a);
- if (!type_isint(n->a->t)) {
- die("not an int");
- }
- typeexpr(n->b);
- if (!type_isint(n->b->t)) {
- die("not an int");
- }
- unify(n->a->t, n->b->t);
- n->t = mktype(TY_INT, 0, 0, 0);
- } else if (kind == N_SUB) {
- typeexpr(n->a);
- if (!type_isint(n->a->t)) {
- die("not an int");
- }
- typeexpr(n->b);
- if (!type_isint(n->b->t)) {
- die("not an int");
- }
- unify(n->a->t, n->b->t);
- n->t = mktype(TY_INT, 0, 0, 0);
- } else if (kind == N_MUL) {
- typeexpr(n->a);
- if (!type_isint(n->a->t)) {
- die("not an int");
- }
- typeexpr(n->b);
- if (!type_isint(n->b->t)) {
- die("not an int");
- }
- unify(n->a->t, n->b->t);
- n->t = mktype(TY_INT, 0, 0, 0);
- } else if (kind == N_DIV) {
- typeexpr(n->a);
- if (!type_isint(n->a->t)) {
- die("not an int");
- }
- typeexpr(n->b);
- if (!type_isint(n->b->t)) {
- die("not an int");
- }
- unify(n->a->t, n->b->t);
- n->t = mktype(TY_INT, 0, 0, 0);
- } else if (kind == N_MOD) {
- typeexpr(n->a);
- if (!type_isint(n->a->t)) {
- die("not an int");
- }
- typeexpr(n->b);
- if (!type_isint(n->b->t)) {
- die("not an int");
- }
- unify(n->a->t, n->b->t);
- n->t = mktype(TY_INT, 0, 0, 0);
- } else if (kind == N_LSH) {
- typeexpr(n->a);
- if (!type_isint(n->a->t)) {
- die("not an int");
- }
- typeexpr(n->b);
- if (!type_isint(n->b->t)) {
- die("not an int");
- }
- n->t = mktype(TY_INT, 0, 0, 0);
- } else if (kind == N_RSH) {
- typeexpr(n->a);
- if (!type_isint(n->a->t)) {
- die("not an int");
- }
- typeexpr(n->b);
- if (!type_isint(n->b->t)) {
- die("not an int");
- }
- n->t = mktype(TY_INT, 0, 0, 0);
- } else if (kind == N_BNOT) {
- typeexpr(n->a);
- if (!type_isprim(n->a->t)) {
- die("not an prim");
- }
- n->t = mktype(TY_INT, 0, 0, 0);
- } else if (kind == N_BOR) {
- typeexpr(n->a);
- if (!type_isprim(n->a->t)) {
- die("not an prim");
- }
- typeexpr(n->b);
- if (!type_isprim(n->b->t)) {
- die("not an prim");
- }
- n->t = mktype(TY_INT, 0, 0, 0);
- } else if (kind == N_BAND) {
- typeexpr(n->a);
- if (!type_isprim(n->a->t)) {
- die("not an prim");
- }
- typeexpr(n->b);
- if (!type_isprim(n->b->t)) {
- die("not an prim");
- }
- n->t = mktype(TY_INT, 0, 0, 0);
- } else if (kind == N_POS) {
- typeexpr(n->a);
- if (!type_isint(n->a->t)) {
- die("not an int");
- }
- n->t = mktype(TY_INT, 0, 0, 0);
- } else if (kind == N_NEG) {
- typeexpr(n->a);
- if (!type_isint(n->a->t)) {
- die("not an int");
- }
- n->t = n->a->t;
- } else if (kind == N_NOT) {
- typeexpr(n->a);
- if (!type_isint(n->a->t)) {
- die("not an int");
- }
- n->t = n->a->t;
- } else if (kind == N_AND) {
- typeexpr(n->a);
- if (!type_isprim(n->a->t)) {
- die("not an prim");
- }
- typeexpr(n->b);
- if (!type_isprim(n->b->t)) {
- die("not an prim");
- }
- n->t = mktype(TY_INT, 0, 0, 0);
- } else if (kind == N_OR) {
- typeexpr(n->a);
- if (!type_isprim(n->a->t)) {
- die("not an prim");
- }
- typeexpr(n->b);
- if (!type_isprim(n->b->t)) {
- die("not an prim");
- }
- n->t = mktype(TY_INT, 0, 0, 0);
- } else if (kind == N_XOR) {
- typeexpr(n->a);
- if (!type_isprim(n->a->t)) {
- die("not an prim");
- }
- typeexpr(n->b);
- if (!type_isprim(n->b->t)) {
- die("not an prim");
- }
- n->t = mktype(TY_INT, 0, 0, 0);
- } else if (kind == N_CAST) {
- typeexpr(n->a);
- if (!type_isprim(n->a->t)) {
- die("not a primitive");
- }
- n->t = prototype(n->b);
- } else {
- die("not an expression");
- }
-}
-
-void
-typelocal(struct node *n)
-{
- unsigned char *name;
- struct type *t;
- struct vdecl *v;
- int size;
-
- name = n->a->s;
- t = prototype(n->b);
-
- v = vfind(curfunc, name, 1);
-
- if (v->defined) {
- die("duplicate variable");
- }
-
- v->t = t;
- v->defined = 1;
-
- size = type_sizeof(t);
-
- curfunc->preamble = curfunc->preamble + size;
- v->offset = -curfunc->preamble;
-
- *link_local = v;
- link_local = &v->next;
-}
-
-void
-typearg(struct node *n, int offset)
-{
- unsigned char *name;
- struct type *t;
- struct vdecl *v;
-
- name = n->a->s;
- t = prototype(n->b);
-
- v = vfind(curfunc, name, 1);
-
- if (v->defined) {
- die("duplicate variable");
- }
-
- v->t = t;
- v->defined = 1;
- v->offset = offset;
-
- *link_arg = v;
- link_arg = &v->next;
-}
-
-// Type a statement
-void
-typestmt(struct node *n)
-{
- int kind;
-
- if (!n) {
- return;
- }
-
- filename = n->filename;
- lineno = n->lineno;
-
- kind = n->kind;
- if (kind == N_CONDLIST) {
- while (1) {
- if (!n) {
- break;
- }
- typestmt(n->a->a);
- typestmt(n->a->b);
- n = n->b;
- }
- } else if (kind == N_STMTLIST) {
- while (1) {
- if (!n) {
- break;
- }
- typestmt(n->a);
- n = n->b;
- }
- } else if (kind == N_LOOP) {
- typestmt(n->a);
- } else if (kind == N_RETURN) {
- if (n->a) {
- if (curfunc->ftype->val->kind == TY_VOID) {
- die("returning a value in a void function");
- }
- typeexpr(n->a);
- unify(n->a->t, curfunc->ftype->val);
- } else {
- if (curfunc->ftype->val->kind != TY_VOID) {
- die("returning void in a non void function");
- }
- }
- } else if (kind == N_VARDECL) {
- typelocal(n);
- } else if (kind != N_BREAK && kind != N_CONTINUE) {
- typeexpr(n);
- }
-}
-
-// Find the first decl in a subtree
-struct decl *
-mindecl(struct decl *d)
-{
- while (1) {
- if (!d || !d->l) {
- return d;
- }
- d = d->l;
- }
-}
-
-// Find the next declaration
-struct decl *
-nextdecl(struct decl *d)
-{
- if (!d) {
- return 0;
- }
-
- if (d->r) {
- return mindecl(d->r);
- }
-
- while (1) {
- if (!d->p) {
- return 0;
- }
- if (d->p->l == d) {
- return d->p;
- }
- d = d->p;
- }
-}
-
-// Find the first declaration
-struct decl *
-firstdecl(void)
-{
- return mindecl(decls);
-}
-
-struct sdecl *
-minsdecl(struct sdecl *d)
-{
- while (1) {
- if (!d || !d->l) {
- return d;
- }
- d = d->l;
- }
-}
-
-struct sdecl *
-sfirst(void)
-{
- return minsdecl(structs);
-}
-
-struct sdecl *
-snext(struct sdecl *d)
-{
- if (!d) {
- return 0;
- }
-
- if (d->r) {
- return minsdecl(d->r);
- }
-
- while (1) {
- if (!d->p) {
- return 0;
- }
- if (d->p->l == d) {
- return d->p;
- }
- d = d->p;
- }
-}
-
-// Define a struct member
-void
-defmember(struct node *n)
-{
- struct mdecl *m;
- unsigned char *name;
-
- name = n->a->s;
-
- m = mfind(curstruct, name);
-
- if (m->defined) {
- die("duplicate memeber");
- }
-
- m->defined = 1;
- m->t = prototype(n->b);
-}
-
-// Define a struct type
-void
-defstruct(struct node *n)
-{
- struct sdecl *d;
- unsigned char *name;
- struct node *m;
-
- name = n->a->s;
-
- if (!cmp(name, (unsigned char *)"int")) {
- die("int is reserved");
- }
-
- if (!cmp(name, (unsigned char *)"byte")) {
- die("byte is reserved");
- }
-
- if (!cmp(name, (unsigned char *)"func")) {
- die("func is reserved");
- }
-
- d = sfind(name);
- if (d->defined) {
- die("duplicate struct");
- }
-
- d->defined = 1;
-
- curstruct = d;
-
- m = n->b;
- while (1) {
- if (!m) {
- break;
- }
-
- defmember(m->a);
-
- m = m->b;
- }
-}
-
-void
-defenum(struct node *n)
-{
- struct edecl *d;
- int i;
-
- n = n->b;
- i = 0;
- while (1) {
- if (!n) {
- break;
- }
-
- d = efind(n->a->a->s, 1);
-
- if (d->defined) {
- die("duplicate enum");
- }
-
- if (n->a->b) {
- i = n->a->b->n;
- }
-
- d->defined = 1;
- d->val = i;
-
- i = i + 1;
- n = n->b;
- }
-}
-
-int
-type_sizeof(struct type *t)
-{
- int kind;
-
- kind = t->kind;
- if (kind == TY_INT) {
- return 8;
- } else if (kind == TY_BYTE) {
- return 8;
- } else if (kind == TY_PTR) {
- return 8;
- } else if (kind == TY_FUNC) {
- return 8;
- } else if (kind == TY_STRUCT) {
- compute_struct(t->s);
- return t->s->size;
- } else {
- die("sizeof: invalid type");
- return 0;
- }
-}
-
-// Depth first compute offset of struct members
-void
-compute_struct(struct sdecl *s)
-{
- struct mdecl *m;
- int size;
-
- if (s->computed) {
- if (s->computed == 2) {
- die("circular reference");
- }
- return;
- }
-
- s->computed = 2;
-
- size = 0;
-
- m = s->vmem;
- while (1) {
- if (!m) {
- break;
- }
-
- m->offset = size;
- size = size + type_sizeof(m->t);
-
- m = m->next;
- }
-
- s->size = size;
- s->computed = 1;
-}
-
-// Evaluate declarations
-void
-typecheck(struct node *p)
-{
- struct sdecl *s;
- struct decl *d;
- struct node *n;
- int kind;
- int offset;
-
- // Process declarations
- n = p;
- while (1) {
- if (!n) {
- break;
- }
-
- kind = n->a->kind;
- if (kind == N_FUNCDECL) {
- declare(n->a);
- } else if (kind == N_FUNC) {
- define(n->a);
- } else if (kind == N_STRUCT) {
- defstruct(n->a);
- } else if (kind == N_ENUM) {
- defenum(n->a);
- } else {
- die("invalid decl");
- }
-
- n = n->b;
- }
-
- // Allocate structs
- s = sfirst();
- while (1) {
- if (!s) {
- break;
- }
-
- compute_struct(s);
-
- s = snext(s);
- }
-
- // Check types
- d = firstdecl();
- while (1) {
- if (!d) {
- break;
- }
-
- curfunc = d;
- link_local = &d->vlocals;
- link_arg = &d->vargs;
-
- offset = 16;
-
- n = d->args;
- while (1) {
- if (!n) {
- break;
- }
-
- typearg(n->a, offset);
-
- n = n->b;
- offset = offset + 8;
- }
-
- typestmt(d->body);
-
- d = nextdecl(d);
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Assembler //
-///////////////////////////////////////////////////////////////////////////////
-
-struct label {
- struct label *next;
- struct fix *fix;
- int at;
- int fixed;
-};
-
-struct fix {
- struct fix *next;
- unsigned char *ptr;
- int at;
-};
-
-struct buf {
- unsigned char *buf;
- int fill;
- int cap;
- struct buf *next;
-};
-
-int at;
-struct label *labels;
-struct buf *text;
-struct buf *text_end;
-
-// Create a new label
-struct label *
-mklabel(void)
-{
- struct label *l;
-
- l = malloc(sizeof(*l));
- if (!l) {
- die("out of memory");
- }
-
- l->next = labels;
- l->fix = 0;
- l->at = 0;
- l->fixed = 0;
-
- labels = l;
-
- return l;
-}
-
-// Reserve size in the output buffer
-void
-reserve(int n)
-{
- unsigned char *m;
- struct buf *b;
-
- if (text_end && text_end->cap - text_end->fill >= n) {
- return;
- }
-
- if (n < 4096) {
- n = 4096;
- }
-
- m = malloc(n);
- if (!m) {
- die("out of memory");
- }
-
- b = malloc(sizeof(*b));
- if (!b) {
- die("out of memory");
- }
-
- b->buf = m;
- b->fill = 0;
- b->cap = n;
- b->next = 0;
-
- if (text_end) {
- text_end->next = b;
- text_end = b;
- } else {
- text = b;
- text_end = b;
- }
-}
-
-// Add a single byte to the output
-void
-emit(int c)
-{
- reserve(1);
- text_end->buf[text_end->fill] = c;
- text_end->fill = text_end->fill + 1;
- at = at + 1;
-}
-
-// Fix a single reference
-void
-fixup(unsigned char *here, int delta)
-{
- here[0] = delta;
- here[1] = delta >> 8;
- here[2] = delta >> 16;
- here[3] = delta >> 24;
-}
-
-// Add an new fixup for the current position
-void
-addfixup(struct label *l)
-{
- struct fix *f;
- unsigned char *here;
-
- reserve(4);
- here = &text_end->buf[text_end->fill];
-
- emit(0);
- emit(0);
- emit(0);
- emit(0);
-
- if (l->fixed) {
- fixup(here, l->at - at);
- } else {
- f = malloc(sizeof(*f));
- if (!f) {
- die("out of memory");
- }
-
- f->next = l->fix;
- f->ptr = here;
- f->at = at;
-
- l->fix = f;
- }
-}
-
-// Fix references to a label to the current position
-void
-fixup_label(struct label *l)
-{
- struct fix *f;
-
- if (l->fixed) {
- die("already fixed");
- }
-
- l->at = at;
- l->fixed = 1;
-
- f = l->fix;
- while (1) {
- if (!f) {
- break;
- }
- fixup(f->ptr, l->at - f->at);
- f = f->next;
- }
-}
-
-void
-emit_ptr(struct label *l)
-{
- // lea %rax, [l]
- emit(0x48);
- emit(0x8d);
- emit(0x05);
- addfixup(l);
- // push %rax
- emit(0x50);
-}
-
-void
-emit_jmp(struct label *l)
-{
- // jmp l
- emit(0xe9);
- addfixup(l);
-}
-
-void
-emit_num(long x)
-{
- // movabs rdx, x
- emit(0x48);
- emit(0xba);
- emit(x);
- emit(x >> 8);
- emit(x >> 16);
- emit(x >> 24);
- emit(x >> 32);
- emit(x >> 40);
- emit(x >> 48);
- emit(x >> 56);
- // push rdx
- emit(0x52);
-}
-
-void
-emit_str(unsigned char *s)
-{
- struct label *a;
- struct label *b;
- int i;
-
- a = mklabel();
- b = mklabel();
-
- // jmp b
- emit_jmp(b);
-
- // a:
- fixup_label(a);
- // .string s
- while (1) {
- if (!*s) {
- break;
- }
- emit(*s);
- s = s + 1;
- }
- emit(0);
-
- // nop sled
- emit(0x90);
- emit(0x90);
- emit(0x90);
- emit(0x90);
- emit(0x90);
- emit(0x90);
- emit(0x90);
- emit(0x90);
-
- // b:
- fixup_label(b);
- // push a
- emit_ptr(a);
-}
-
-void
-emit_pop(int n)
-{
- n = n * 8;
- // add rsp, 8*n
- emit(0x48);
- emit(0x81);
- emit(0xc4);
- emit(n);
- emit(n >> 8);
- emit(n >> 16);
- emit(n >> 24);
-}
-
-void
-emit_preamble(int n, int start)
-{
- int i;
- if (start) {
- // xor rbp, rbp
- emit(0x48);
- emit(0x33);
- emit(0xed);
- // mov rdi, [rsp]
- emit(0x48);
- emit(0x8b);
- emit(0x3c);
- emit(0x24);
- // lea rsi, [rsp + 8]
- emit(0x48);
- emit(0x8d);
- emit(0x74);
- emit(0x24);
- emit(0x08);
- // lea rdx, [rsi + rdi * 8 + 8]
- emit(0x48);
- emit(0x8d);
- emit(0x54);
- emit(0xfe);
- emit(0x08);
- // push rdx
- emit(0x52);
- // push rsi
- emit(0x56);
- // push rdi
- emit(0x57);
- // push rbp
- emit(0x55);
- }
- // push rbp
- emit(0x55);
- // mov rbp, rsp
- emit(0x48);
- emit(0x8b);
- emit(0xec);
- i = 0;
- while (1) {
- if (i >= n) {
- break;
- }
- emit_num(0);
- i = i + 8;
- }
-}
-
-void
-emit_store(struct type *t)
-{
- // pop rdi
- emit(0x5f);
- // pop rax
- emit(0x58);
- if (t->kind == TY_BYTE) {
- // mov [rdi], al
- emit(0x40);
- emit(0x88);
- emit(0x07);
- } else if (type_isprim(t)) {
- // mov [rdi], rax
- emit(0x48);
- emit(0x89);
- emit(0x07);
- } else {
- die("invalid store");
- }
- // push rax
- emit(0x50);
-}
-
-void
-emit_load(struct type *t)
-{
- // pop rdi
- emit(0x5f);
- if (t->kind == TY_BYTE) {
- // xor rax, rax
- emit(0x48);
- emit(0x33);
- emit(0xc0);
- // mov al, [rdi]
- emit(0x40);
- emit(0x8a);
- emit(0x07);
- } else if (type_isprim(t)) {
- // mov rax, [rdi]
- emit(0x48);
- emit(0x8b);
- emit(0x07);
- } else {
- die("invalid load");
- }
- // push rax
- emit(0x50);
-}
-
-void
-emit_jz(struct label *l)
-{
- // pop rax
- emit(0x58);
- // test rax, rax
- emit(0x48);
- emit(0x85);
- emit(0xc0);
- // jz no
- emit(0x0f);
- emit(0x84);
- addfixup(l);
-}
-
-void
-emit_lea(struct vdecl *v)
-{
- int offset;
- offset = v->offset;
- if (offset >= -128 && offset <= 127) {
- // lea rax, [rbp + v]
- emit(0x48);
- emit(0x8d);
- emit(0x45);
- emit(offset);
- } else {
- // lea rax, [rbp + v]
- emit(0x48);
- emit(0x8d);
- emit(0x85);
- emit(offset);
- emit(offset >> 8);
- emit(offset >> 16);
- emit(offset >> 24);
- }
- // push rax
- emit(0x50);
-}
-
-void
-emit_and(void)
-{
- // pop rax
- emit(0x58);
- // pop rdx
- emit(0x5a);
- // and rdx, rax
- emit(0x48);
- emit(0x23);
- emit(0xc2);
- // push rax
- emit(0x50);
-}
-
-void
-emit_or(void)
-{
- // pop rax
- emit(0x58);
- // pop rdx
- emit(0x5a);
- // or rdx, rax
- emit(0x48);
- emit(0x0b);
- emit(0xc2);
- // push rax
- emit(0x50);
-}
-
-void
-emit_xor(void)
-{
- // pop rax
- emit(0x58);
- // pop rdx
- emit(0x5a);
- // xor rdx, rax
- emit(0x48);
- emit(0x33);
- emit(0xc2);
- // push rax
- emit(0x50);
-}
-
-void
-emit_add(void)
-{
- // pop rax
- emit(0x58);
- // pop rdx
- emit(0x5a);
- // add rdx, rax
- emit(0x48);
- emit(0x03);
- emit(0xc2);
- // push rax
- emit(0x50);
-}
-
-void
-emit_ret(void)
-{
- // pop rax
- emit(0x58);
- // mov rsp, rbp
- emit(0x48);
- emit(0x8b);
- emit(0xe5);
- // pop rbp
- emit(0x5d);
- // ret
- emit(0xc3);
-}
-
-void
-emit_lcall(struct label *l, int n)
-{
- // call l
- emit(0xe8);
- addfixup(l);
- // add rsp, 8*(n+1)
- emit_pop(n);
- // push rax
- emit(0x50);
-}
-
-void
-emit_call(int n)
-{
- // pop rax
- emit(0x58);
- // call rax
- emit(0xff);
- emit(0xd0);
- // add rsp, 8*(n+1)
- emit_pop(n);
- // push rax
- emit(0x50);
-}
-
-void
-emit_gt(void)
-{
- // pop rdx
- emit(0x5a);
- // pop rcx
- emit(0x59);
- // xor rax, rax
- emit(0x48);
- emit(0x33);
- emit(0xc0);
- // cmp rdx, rcx
- emit(0x48);
- emit(0x3b);
- emit(0xd1);
- // setg al
- emit(0x48);
- emit(0x0f);
- emit(0x9f);
- emit(0xc0);
- // mov rax
- emit(0x50);
-}
-
-void
-emit_lt(void)
-{
- // pop rdx
- emit(0x5a);
- // pop rcx
- emit(0x59);
- // xor rax, rax
- emit(0x48);
- emit(0x33);
- emit(0xc0);
- // cmp rdx, rcx
- emit(0x48);
- emit(0x3b);
- emit(0xd1);
- // setl al
- emit(0x48);
- emit(0x0f);
- emit(0x9c);
- emit(0xc0);
- // mov rax
- emit(0x50);
-}
-
-void
-emit_ge(void)
-{
- // pop rdx
- emit(0x5a);
- // pop rcx
- emit(0x59);
- // xor rax, rax
- emit(0x48);
- emit(0x33);
- emit(0xc0);
- // cmp rdx, rcx
- emit(0x48);
- emit(0x3b);
- emit(0xd1);
- // setge al
- emit(0x48);
- emit(0x0f);
- emit(0x9d);
- emit(0xc0);
- // mov rax
- emit(0x50);
-}
-
-void
-emit_le(void)
-{
- // pop rdx
- emit(0x5a);
- // pop rcx
- emit(0x59);
- // xor rax, rax
- emit(0x48);
- emit(0x33);
- emit(0xc0);
- // cmp rdx, rcx
- emit(0x48);
- emit(0x3b);
- emit(0xd1);
- // setle al
- emit(0x48);
- emit(0x0f);
- emit(0x9e);
- emit(0xc0);
- // mov rax
- emit(0x50);
-}
-
-void
-emit_eq(void)
-{
- // pop rdx
- emit(0x5a);
- // pop rcx
- emit(0x59);
- // xor rax, rax
- emit(0x48);
- emit(0x33);
- emit(0xc0);
- // cmp rdx, rcx
- emit(0x48);
- emit(0x3b);
- emit(0xd1);
- // sete al
- emit(0x48);
- emit(0x0f);
- emit(0x94);
- emit(0xc0);
- // mov rax
- emit(0x50);
-}
-
-void
-emit_ne(void)
-{
- // pop rdx
- emit(0x5a);
- // pop rcx
- emit(0x59);
- // xor rax, rax
- emit(0x48);
- emit(0x33);
- emit(0xc0);
- // cmp rdx, rcx
- emit(0x48);
- emit(0x3b);
- emit(0xd1);
- // setne al
- emit(0x48);
- emit(0x0f);
- emit(0x95);
- emit(0xc0);
- // mov rax
- emit(0x50);
-}
-
-void
-emit_sub(void)
-{
- // pop rax
- emit(0x58);
- // pop rdx
- emit(0x5a);
- // sub rax, rdx
- emit(0x48);
- emit(0x2b);
- emit(0xc2);
- // push rax
- emit(0x50);
-}
-
-void
-emit_mul(void)
-{
- // pop rax
- emit(0x58);
- // pop rcx
- emit(0x59);
- // mul rcx
- emit(0x48);
- emit(0xf7);
- emit(0xe1);
- // push rax
- emit(0x50);
-}
-
-void
-emit_div(void)
-{
- // pop rax
- emit(0x58);
- // pop rcx
- emit(0x59);
- // xor rdx, rdx
- emit(0x48);
- emit(0x33);
- emit(0xd2);
- // test rax, rax
- emit(0x48);
- emit(0x85);
- emit(0xc0);
- // sets dl
- emit(0x48);
- emit(0x0f);
- emit(0x98);
- emit(0xc2);
- // neg rdx
- emit(0x48);
- emit(0xf7);
- emit(0xda);
- // idiv rcx
- emit(0x48);
- emit(0xf7);
- emit(0xf9);
- // push rax
- emit(0x50);
-}
-
-void
-emit_mod(void)
-{
- // pop rax
- emit(0x58);
- // pop rcx
- emit(0x59);
- // xor rdx, rdx
- emit(0x48);
- emit(0x33);
- emit(0xd2);
- // test rax, rax
- emit(0x48);
- emit(0x85);
- emit(0xc0);
- // sets dl
- emit(0x48);
- emit(0x0f);
- emit(0x98);
- emit(0xc2);
- // neg rdx
- emit(0x48);
- emit(0xf7);
- emit(0xda);
- // idiv rcx
- emit(0x48);
- emit(0xf7);
- emit(0xf9);
- // push rdx
- emit(0x52);
-}
-
-void
-emit_lsh(void)
-{
- // pop rax
- emit(0x58);
- // pop rcx
- emit(0x59);
- // shl rax, cl
- emit(0x48);
- emit(0xd3);
- emit(0xe0);
- // push rax
- emit(0x50);
-}
-
-void
-emit_rsh(void)
-{
- // pop rax
- emit(0x58);
- // pop rcx
- emit(0x59);
- // shr rax, cl
- emit(0x48);
- emit(0xd3);
- emit(0xe8);
- // push rax
- emit(0x50);
-}
-
-void
-emit_not(void)
-{
- // pop rax
- emit(0x58);
- // neg rax
- emit(0x48);
- emit(0xf7);
- emit(0xd0);
- // push rax
- emit(0x50);
-}
-
-void
-emit_neg(void)
-{
- // pop rax
- emit(0x58);
- // neg rax
- emit(0x48);
- emit(0xf7);
- emit(0xd8);
- // push rax
- emit(0x50);
-}
-
-// Write the output
-void
-writeout(void)
-{
- int i;
- int load_addr;
- int entry;
- struct decl *d;
- struct buf *b;
- int kentry;
- int magic;
- int flags;
- int checksum;
- int addr;
- int end;
-
- d = find((unsigned char *)"_start");
- if (!d->defined || !d->label->fixed) {
- die("no _start function");
- }
-
- load_addr = 0x100000;
- entry = load_addr + d->label->at + 128 + 32;
- at = at + 128 + 32;
- end = load_addr + at;
-
- magic = 0x1badb002;
- flags = 0x00010003;
- checksum = -(magic + flags);
- addr = load_addr + 120;
-
- d = find((unsigned char *)"_kstart");
- if (d->defined && d->label->fixed) {
- kentry = load_addr + d->label->at +128 + 32;
- } else {
- magic = 0;
- kentry = 0;
- }
-
- // magic
- fputc(0x7f, fout);
- fputc('E', fout);
- fputc('L', fout);
- fputc('F', fout);
-
- // class
- fputc(2, fout);
-
- // endian
- fputc(1, fout);
-
- // version
- fputc(1, fout);
-
- // abi
- fputc(0, fout);
-
- // abi version
- fputc(0, fout);
-
- // padding
- fputc(0, fout);
- fputc(0, fout);
- fputc(0, fout);
- fputc(0, fout);
- fputc(0, fout);
- fputc(0, fout);
- fputc(0, fout);
-
- // type
- fputc(2, fout);
- fputc(0, fout);
-
- // machine
- fputc(62, fout);
- fputc(0, fout);
-
- // version
- fputc(1, fout);
- fputc(0, fout);
- fputc(0, fout);
- fputc(0, fout);
-
- // entry point
- fputc(entry, fout);
- fputc(entry >> 8, fout);
- fputc(entry >> 16, fout);
- fputc(entry >> 24, fout);
- fputc(0, fout);
- fputc(0, fout);
- fputc(0, fout);
- fputc(0, fout);
-
- // phoff
- fputc(64, fout);
- fputc(0, fout);
- fputc(0, fout);
- fputc(0, fout);
- fputc(0, fout);
- fputc(0, fout);
- fputc(0, fout);
- fputc(0, fout);
-
- // shoff
- fputc(0, fout);
- fputc(0, fout);
- fputc(0, fout);
- fputc(0, fout);
- fputc(0, fout);
- fputc(0, fout);
- fputc(0, fout);
- fputc(0, fout);
-
- // flags
- fputc(0, fout);
- fputc(0, fout);
- fputc(0, fout);
- fputc(0, fout);
-
- // ehsize
- fputc(64, fout);
- fputc(0, fout);
-
- // phentsize
- fputc(56, fout);
- fputc(0, fout);
-
- // phnum
- fputc(1, fout);
- fputc(0, fout);
-
- // shentsize
- fputc(64, fout);
- fputc(0, fout);
-
- // shnum
- fputc(0, fout);
- fputc(0, fout);
-
- // shstrndx
- fputc(0, fout);
- fputc(0, fout);
-
- // phdr[0].type
- fputc(1, fout);
- fputc(0, fout);
- fputc(0, fout);
- fputc(0, fout);
-
- // phdr[0].flags
- fputc(5, fout);
- fputc(0, fout);
- fputc(0, fout);
- fputc(0, fout);
-
- // phdr[0].offset
- fputc(0, fout);
- fputc(0, fout);
- fputc(0, fout);
- fputc(0, fout);
- fputc(0, fout);
- fputc(0, fout);
- fputc(0, fout);
- fputc(0, fout);
-
- // phdr[0].vaddr
- fputc(load_addr, fout);
- fputc(load_addr >> 8, fout);
- fputc(load_addr >> 16, fout);
- fputc(load_addr >> 24, fout);
- fputc(0, fout);
- fputc(0, fout);
- fputc(0, fout);
- fputc(0, fout);
-
- // phdr[0].paddr
- fputc(0, fout);
- fputc(0, fout);
- fputc(0, fout);
- fputc(0, fout);
- fputc(0, fout);
- fputc(0, fout);
- fputc(0, fout);
- fputc(0, fout);
-
- // phdr[0].filesize
- fputc(at, fout);
- fputc(at >> 8, fout);
- fputc(at >> 16, fout);
- fputc(at >> 24, fout);
- fputc(0, fout);
- fputc(0, fout);
- fputc(0, fout);
- fputc(0, fout);
-
- // phdr[0].memsize
- fputc(at, fout);
- fputc(at >> 8, fout);
- fputc(at >> 16, fout);
- fputc(at >> 24, fout);
- fputc(0, fout);
- fputc(0, fout);
- fputc(0, fout);
- fputc(0, fout);
-
- // phdr[0].align
- fputc(0, fout);
- fputc(0, fout);
- fputc(0, fout);
- fputc(0, fout);
- fputc(0, fout);
- fputc(0, fout);
- fputc(0, fout);
- fputc(0, fout);
-
- // mb.magic
- fputc(magic, fout);
- fputc(magic >> 8, fout);
- fputc(magic >> 16, fout);
- fputc(magic >> 24, fout);
-
- // mb.flags
- fputc(flags, fout);
- fputc(flags >> 8, fout);
- fputc(flags >> 16, fout);
- fputc(flags >> 24, fout);
-
- // mb.checksum
- fputc(checksum, fout);
- fputc(checksum >> 8, fout);
- fputc(checksum >> 16, fout);
- fputc(checksum >> 24, fout);
-
- // mb.header
- fputc(addr, fout);
- fputc(addr >> 8, fout);
- fputc(addr >> 16, fout);
- fputc(addr >> 24, fout);
-
- // mb.load
- fputc(load_addr, fout);
- fputc(load_addr >> 8, fout);
- fputc(load_addr >> 16, fout);
- fputc(load_addr >> 24, fout);
-
- // mb.load_end
- fputc(end, fout);
- fputc(end >> 8, fout);
- fputc(end >> 16, fout);
- fputc(end >> 24, fout);
-
- // mb.bss_end
- fputc(0, fout);
- fputc(0, fout);
- fputc(0, fout);
- fputc(0, fout);
-
- // mb.entry
- fputc(kentry, fout);
- fputc(kentry >> 8, fout);
- fputc(kentry >> 16, fout);
- fputc(kentry >> 24, fout);
-
- // nop sled
- fputc(0x90, fout);
- fputc(0x90, fout);
- fputc(0x90, fout);
- fputc(0x90, fout);
- fputc(0x90, fout);
- fputc(0x90, fout);
- fputc(0x90, fout);
- fputc(0x90, fout);
-
- // text
- b = text;
- while (1) {
- if (!b) {
- break;
- }
- i = 0;
- while (1) {
- if (i >= b->fill) {
- break;
- }
- fputc(b->buf[i], fout);
- i = i + 1;
- }
- b = b->next;
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// stdlib //
-///////////////////////////////////////////////////////////////////////////////
-
-// Define "stdlib" functions
-void
-add_stdlib(void)
-{
- struct label *a;
- struct label *b;
- struct decl *d;
-
- d = find((unsigned char *)"syscall");
- if (!d->defined) {
- d->defined = 1;
- fixup_label(d->label);
- // push rbp
- emit(0x55);
- // mov rbp, rsp
- emit(0x48);
- emit(0x8b);
- emit(0xec);
- // mov rax, [rbp + 16]
- emit(0x48);
- emit(0x8b);
- emit(0x45);
- emit(0x10);
- // mov rdi, [rbp + 24]
- emit(0x48);
- emit(0x8b);
- emit(0x7d);
- emit(0x18);
- // mov rsi, [rbp + 32]
- emit(0x48);
- emit(0x8b);
- emit(0x75);
- emit(0x20);
- // mov rdx, [rbp + 40]
- emit(0x48);
- emit(0x8b);
- emit(0x55);
- emit(0x28);
- // mov r10, [rbp + 48]
- emit(0x4c);
- emit(0x8b);
- emit(0x55);
- emit(0x30);
- // mov r8, [rbp + 56]
- emit(0x4c);
- emit(0x8b);
- emit(0x45);
- emit(0x38);
- // mov r9, [rbp + 64]
- emit(0x4c);
- emit(0x8b);
- emit(0x4d);
- emit(0x40);
- // syscall
- emit(0x0f);
- emit(0x05);
- // push rax
- emit(0x50);
- // pop rax
- emit(0x58);
- // mov rsp, rbp
- emit(0x48);
- emit(0x8b);
- emit(0xe5);
- // pop rbp
- emit(0x5d);
- // ret
- emit(0xc3);
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Code Generation //
-///////////////////////////////////////////////////////////////////////////////
-
-// Translate an expression
-void
-texpr(struct node *n, int rhs)
-{
- struct decl *d;
- struct vdecl *v;
- struct edecl *e;
- struct node *a;
- struct label *no;
- struct label *out;
- int nargs;
- int kind;
- int offset;
-
- kind = n->kind;
- if (kind == N_IDENT) {
- e = efind(n->s, 0);
- if (e) {
- emit_num(e->val);
- } else {
- v = vfind(curfunc, n->s, 0);
- if (v) {
- emit_lea(v);
- if (rhs) {
- emit_load(n->t);
- }
- } else {
- d = find(n->s);
- emit_ptr(d->label);
- }
- }
- } else if (kind == N_NUM) {
- if (!rhs) {
- die("num is not an lexpr");
- }
- emit_num(n->n);
- } else if (kind == N_CHAR) {
- if (!rhs) {
- die("char is not an lexpr");
- }
- emit_num(n->n);
- } else if (kind == N_STR) {
- if (!rhs) {
- die("str is not an lexpr");
- }
- emit_str(n->s);
- } else if (kind == N_EXPRLIST) {
- if (n->b) {
- texpr(n->b, 1);
- }
- texpr(n->a, 1);
- } else if (kind == N_CALL) {
- if (!rhs) {
- die("call is not an lexpr");
- }
- nargs = 0;
- a = n->b;
- while (1) {
- if (!a) {
- break;
- }
- nargs = nargs + 1;
- a = a->b;
- }
- if (n->b) {
- texpr(n->b, 1);
- }
- if (n->a->kind == N_IDENT) {
- v = vfind(curfunc, n->a->s, 0);
- if (v) {
- emit_lea(v);
- emit_load(n->a->t);
- emit_call(nargs);
- } else {
- d = find(n->a->s);
- emit_lcall(d->label, nargs);
- }
- } else {
- texpr(n->a, 0);
- emit_call(nargs);
- }
- } else if (kind == N_DOT) {
- texpr(n->a, 0);
- if (n->a->t->kind == TY_PTR) {
- emit_load(n->a->t);
- }
- emit_num(n->offset);
- emit_add();
- if (rhs) {
- emit_load(n->t);
- }
- } else if (kind == N_ASSIGN) {
- if (!rhs) {
- die("assign is not an lexpr");
- }
- texpr(n->b, 1);
- texpr(n->a, 0);
- emit_store(n->t);
- } else if (kind == N_SIZEOF) {
- if (!rhs) {
- die("sizeof is not an lexpr");
- }
- out = mklabel();
- emit_jmp(out);
- texpr(n->a, 0);
- fixup_label(out);
- if (n->a->t->kind == TY_BYTE) {
- emit_num(1);
- } else {
- emit_num(type_sizeof(n->a->t));
- }
- } else if (kind == N_REF) {
- if (!rhs) {
- die("ref is not an lexpr");
- }
- texpr(n->a, 0);
- } else if (kind == N_DEREF) {
- texpr(n->a, 1);
- if (rhs) {
- emit_load(n->t);
- }
- } else if (kind == N_INDEX) {
- texpr(n->a, 1);
- texpr(n->b, 1);
- emit_num(n->offset);
- emit_mul();
- emit_add();
- if (rhs) {
- emit_load(n->t);
- }
- } else if (kind == N_LT) {
- if (!rhs) {
- die("not lexpr");
- }
- texpr(n->b, 1);
- texpr(n->a, 1);
- emit_lt();
- } else if (kind == N_GT) {
- if (!rhs) {
- die("not lexpr");
- }
- texpr(n->b, 1);
- texpr(n->a, 1);
- emit_gt();
- } else if (kind == N_LE) {
- if (!rhs) {
- die("not lexpr");
- }
- texpr(n->b, 1);
- texpr(n->a, 1);
- emit_le();
- } else if (kind == N_GE) {
- if (!rhs) {
- die("not lexpr");
- }
- texpr(n->b, 1);
- texpr(n->a, 1);
- emit_ge();
- } else if (kind == N_EQ) {
- if (!rhs) {
- die("not lexpr");
- }
- texpr(n->b, 1);
- texpr(n->a, 1);
- emit_eq();
- } else if (kind == N_NE) {
- if (!rhs) {
- die("not lexpr");
- }
- texpr(n->b, 1);
- texpr(n->a, 1);
- emit_ne();
- } else if (kind == N_ADD) {
- if (!rhs) {
- die("not lexpr");
- }
- texpr(n->b, 1);
- texpr(n->a, 1);
- emit_add();
- } else if (kind == N_SUB) {
- if (!rhs) {
- die("not lexpr");
- }
- texpr(n->b, 1);
- texpr(n->a, 1);
- emit_sub();
- } else if (kind == N_MUL) {
- if (!rhs) {
- die("not lexpr");
- }
- texpr(n->b, 1);
- texpr(n->a, 1);
- emit_mul();
- } else if (kind == N_DIV) {
- if (!rhs) {
- die("not lexpr");
- }
- texpr(n->b, 1);
- texpr(n->a, 1);
- emit_div();
- } else if (kind == N_MOD) {
- if (!rhs) {
- die("not lexpr");
- }
- texpr(n->b, 1);
- texpr(n->a, 1);
- emit_mod();
- } else if (kind == N_LSH) {
- if (!rhs) {
- die("not lexpr");
- }
- texpr(n->b, 1);
- texpr(n->a, 1);
- emit_lsh();
- } else if (kind == N_RSH) {
- if (!rhs) {
- die("not lexpr");
- }
- texpr(n->b, 1);
- texpr(n->a, 1);
- emit_rsh();
- } else if (kind == N_BNOT) {
- if (!rhs) {
- die("not lexpr");
- }
- no = mklabel();
- out = mklabel();
- texpr(n->a, 1);
- emit_jz(no);
- emit_num(0);
- emit_jmp(out);
- fixup_label(no);
- emit_num(1);
- fixup_label(out);
- } else if (kind == N_BOR) {
- if (!rhs) {
- die("not lexpr");
- }
- no = mklabel();
- out = mklabel();
- texpr(n->a, 1);
- emit_jz(no);
- emit_num(1);
- emit_jmp(out);
- fixup_label(no);
- no = mklabel();
- texpr(n->b, 1);
- emit_jz(no);
- emit_num(1);
- emit_jmp(out);
- fixup_label(no);
- emit_num(0);
- fixup_label(out);
- } else if (kind == N_BAND) {
- if (!rhs) {
- die("not lexpr");
- }
- no = mklabel();
- out = mklabel();
- texpr(n->a, 1);
- emit_jz(no);
- texpr(n->b, 1);
- emit_jz(no);
- emit_num(1);
- emit_jmp(out);
- fixup_label(no);
- emit_num(0);
- fixup_label(out);
- } else if (kind == N_POS) {
- if (!rhs) {
- die("not lexpr");
- }
- texpr(n->a, 1);
- } else if (kind == N_NEG) {
- if (!rhs) {
- die("not lexpr");
- }
- texpr(n->a, 1);
- emit_neg();
- } else if (kind == N_CAST) {
- if (!rhs) {
- die("not lexpr");
- }
- texpr(n->a, 1);
- } else if (kind == N_NOT) {
- if (!rhs) {
- die("not lexpr");
- }
- texpr(n->a, 1);
- emit_not();
- } else if (kind == N_AND) {
- if (!rhs) {
- die("not lexpr");
- }
- texpr(n->b, 1);
- texpr(n->a, 1);
- emit_and();
- } else if (kind == N_OR) {
- if (!rhs) {
- die("not lexpr");
- }
- texpr(n->b, 1);
- texpr(n->a, 1);
- emit_or();
- } else if (kind == N_XOR) {
- if (!rhs) {
- die("not lexpr");
- }
- texpr(n->b, 1);
- texpr(n->a, 1);
- emit_xor();
- } else {
- die("invalid expr");
- }
-}
-
-// Loop top and loop out
-struct label *ltop;
-struct label *lout;
-
-// Translate a statement
-void
-tstmt(struct node *n)
-{
- struct label *out;
- struct label *no;
- struct label *saved_top;
- struct label *saved_out;
- int kind;
-
- if (!n) {
- return;
- }
-
- kind = n->kind;
- if (kind == N_CONDLIST) {
- out = mklabel();
- no = 0;
- while (1) {
- if (no) {
- fixup_label(no);
- }
- if (!n) {
- break;
- }
- no = mklabel();
-
- if (n->a->a) {
- texpr(n->a->a, 1);
- emit_jz(no);
- }
-
- tstmt(n->a->b);
- emit_jmp(out);
- n = n->b;
- }
- fixup_label(out);
- } else if (kind == N_STMTLIST) {
- while (1) {
- if (!n) {
- break;
- }
- tstmt(n->a);
- n = n->b;
- }
- } else if (kind == N_LOOP) {
- saved_top = ltop;
- saved_out = lout;
- ltop = mklabel();
- lout = mklabel();
- fixup_label(ltop);
- tstmt(n->a);
- emit_jmp(ltop);
- fixup_label(lout);
- ltop = saved_top;
- lout = saved_out;
- } else if (kind == N_BREAK) {
- if (!ltop) {
- die("break outside loop");
- }
- emit_jmp(lout);
- } else if (kind == N_CONTINUE) {
- if (!ltop) {
- die("continue outside loop");
- }
- emit_jmp(ltop);
- } else if (kind == N_RETURN) {
- if (n->a) {
- texpr(n->a, 1);
- } else {
- emit_num(0);
- }
- emit_ret();
- } else if (kind != N_VARDECL) {
- texpr(n, 1);
- emit_pop(1);
- }
-}
-
-// Translate a function
-void
-tfunc(struct decl *d)
-{
- struct node *n;
-
- if (!d->defined) {
- return;
- }
-
- curfunc = d;
-
- emit_str(d->name);
-
- fixup_label(d->label);
-
- emit_preamble(d->preamble, !cmp(d->name, (unsigned char *)"_start"));
-
- tstmt(d->body);
-
- emit_num(0);
-
- if (!cmp(d->name, (unsigned char *)"_start")) {
- emit(0x0f);
- emit(0x0b);
- }
-
- emit_ret();
-}
-
-// Translate all functions
-void
-translate(struct node *p)
-{
- struct decl *d;
-
- d = firstdecl();
- while (1) {
- if (!d) {
- break;
- }
- tfunc(d);
- d = nextdecl(d);
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Main //
-///////////////////////////////////////////////////////////////////////////////
-
-int
-main(int argc, char **argv)
-{
- struct node *p;
- int i;
-
- // Setup the compiler
- setup();
-
- p = 0;
- i = 1;
- while (1) {
- if (i >= argc) {
- break;
- }
-
- if (!cmp((unsigned char *)argv[i], (unsigned char *)"-o")) {
- i = i + 1;
- if (i >= argc) {
- die("invalid -o at end of argument list");
- }
-
- open_output((unsigned char *)argv[i]);
-
- i = i + 1;
- continue;
- }
-
- open_source((unsigned char *)argv[i]);
-
- // Parse the program
- p = program(p);
-
- close_source();
-
- i = i + 1;
- }
-
- // Verify types
- typecheck(p);
-
- // Generate code
- translate(p);
-
- if (fout == stdout) {
- open_output((unsigned char *)"a.out");
- }
-
- // Define _start, syscall
- add_stdlib();
-
- // Write output
- writeout();
-
- return 0;
-}
diff --git a/attic/cc3.l b/attic/cc3.l
@@ -1,52 +0,0 @@
-COMMENT = "//";
-WHITESPACE = [ \r\n\t];
-IDENT = [a-zA-Z_][a-zA-Z0-9_]*;
-STR = "\""([^"\\]|"\\".)*"\"";
-CHR = "'"([^'\\]|"\\".)*"'";
-DEC = [0-9]+;
-HEX = "0x"[0-9a-fA-F]*;
-LPAR = "(";
-RPAR = ")";
-LBRA = "{";
-RBRA = "}";
-COMMA = ",";
-SEMI = ";";
-COLON = ":";
-STAR = "*";
-EQUAL = "=";
-EQ = "==";
-AND = "&";
-ANDTHEN = "&&";
-OR = "|";
-ORELSE = "||";
-XOR = "^";
-BANG = "!";
-NE = "!=";
-LT = "<";
-LSH = "<<";
-LE = "<=";
-GT = ">";
-RSH = ">>";
-GE = ">=";
-RSQ = "[";
-LSQ = "]";
-PLUS = "+";
-MINUS = "-";
-MOD = "%";
-RETURN = "return";
-BREAK = "break";
-SIZEOF = "sizeof";
-IF = "if";
-ELSE = "else";
-LOOP = "loop";
-CONTINUE = "continue";
-GOTO = "goto";
-VAR = "var";
-ENUM = "enum";
-STRUCT = "struct";
-BYTE = "byte";
-INT = "int";
-VOID = "void";
-DOT = ".";
-NOT = "~";
-DIV = "/";
diff --git a/attic/cc3.y b/attic/cc3.y
@@ -1,152 +0,0 @@
-start program;
-
-primary: ident
- | num
- | hex
- | str
- | chr
- | lpar expr rpar
-;
-
-expr_list: expr
- | expr comma expr_list
-;
-
-post_expr: primary
- | sizeof lpar expr rpar
- | post_expr lsq expr rsq
- | post_expr lpar expr_list rpar
- | post_expr dot ident
- | post_expr colon type
-;
-
-unary_expr : post_expr
- | and unary_expr
- | star unary_expr
- | plus unary_expr
- | minus unary_expr
- | tilde unary_expr
- | bang unary_expr
-;
-
-shift_expr : unary_expr
- | unary_expr lsh shift_expr
- | unary_expr rsh shift_expr
-;
-
-mul_expr : shift_expr
- | shift_expr star mul_expr
- | shift_expr div mul_expr
- | shift_expr mod mul_expr
- | shift_expr and mul_expr
-;
-
-add_expr : mul_expr
- | mul_expr plus add_expr
- | mul_expr minus add_expr
- | mul_expr or add_expr
- | mul_expr xor add_expr
-;
-
-comp_expr : add_expr
- | add_expr lt add_expr
- | add_expr gt add_expr
- | add_expr le add_expr
- | add_expr gt add_expr
- | add_expr eq add_expr
- | add_expr ne add_expr
-;
-
-bool_expr : bool_expr
- | add_expr and_then bool_expr
- | add_expr or_else bool_expr
-;
-
-expr : bool_expr
- | bool_expr equal expr
-;
-
-if_stmt : if expr lbra stmt_list rbra
- | if expr lbra stmt_list rbra else if_stmt
- | if expr lbra stmt_list rbra else lbra stmt_list rbra
-;
-
-loop_stmt : loop lbra stmt_list rbra;
-
-break_stmt : break;
-
-continue_stmt : continue;
-
-return_stmt : return;
- | return expr
-;
-
-var_decl : ident colon type;
-
-var_stmt : var var_decl;
-
-label_stmt : colon ident
-
-goto_stmt : goto ident;
-
-stmt : if_stmt
- | loop_stmt
- | break_stmt semi
- | continue_stmt semi
- | return_stmt semi
- | var_stmt semi
- | label_stmt semi
- | goto_stmt semi
- | expr semi
-;
-
-stmt_list : stmt
- | stmt stmt_list
-;
-
-enum_list : ident
- | enum_list comma enum_list
-;
-
-enum_decl : enum ident lbra enum_list rbra;
-
-type : ident
- | star type
- | lpar type rpar
- | func func_type
-;
-
-member_decl : ident colon type;
-
-member_list : member_decl
- | member_decl semi member_list
-;
-
-struct_decl : struct ident lbra member_list rbra;
-
-arg_decl : colon type
- ident colon type
-;
-
-arg_list : arg_decl
- | arg_decl comma arg_list
-;
-
-func_type : lpar rpar colon type
- | lpar arg_list rpar colon type
-;
-
-func_decl : ident func_type;
-
-func_def : func_decl lbra stmt_list rbra
- | func_decl semi
-;
-
-decl : enum_decl
- | struct_decl
- | func_def
-;
-
-program : decl
- | decl program
-;
diff --git a/attic/chacha20_test.om b/attic/chacha20_test.om
@@ -1,49 +0,0 @@
-main(c:int,v:**byte,e:**byte) {
- var _key: _chacha20_state;
- var key: *byte;
- var _nonce: _chacha20_state;
- var nonce: *byte;
- var _block: _chacha20_state;
- var block: *byte;
-
- key = (&_key):*byte;
- nonce = (&_nonce):*byte;
- block = (&_block):*byte;
-
- bzero(key, sizeof(_key));
- bzero(nonce, sizeof(_nonce));
-
- chacha20_block(block, key, 0, nonce);
- fdputd(1, 1);
- fdputs(1, ":\n");
- fdxxd(1, block, 64);
- fdputc(1, '\n');
-
- chacha20_block(block, key, 1, nonce);
- fdputd(1, 2);
- fdputs(1, ":\n");
- fdxxd(1, block, 64);
- fdputc(1, '\n');
-
- key[31] = 1:byte;
- chacha20_block(block, key, 1, nonce);
- fdputd(1, 3);
- fdputs(1, ":\n");
- fdxxd(1, block, 64);
- fdputc(1, '\n');
-
- key[1] = 0xff:byte;
- key[31] = 0:byte;
- chacha20_block(block, key, 2, nonce);
- fdputd(1, 4);
- fdputs(1, ":\n");
- fdxxd(1, block, 64);
- fdputc(1, '\n');
-
- key[1] = 0:byte;
- nonce[11] = 2:byte;
- chacha20_block(block, key, 0, nonce);
- fdputd(1, 5);
- fdputs(1, ":\n");
- fdxxd(1, block, 64);
-}
diff --git a/attic/cout.om b/attic/cout.om
@@ -1,628 +0,0 @@
-func ctranslate(c: *compiler) {
- var d: *decl;
- var seen: int;
- var has_enum: int;
-
- fputs(c.cout, "#ifndef my__start\n");
- fputs(c.cout, "#define my__start main\n");
- fputs(c.cout, "#endif\n");
- fputs(c.cout, "#ifndef my_syscall\n");
- fputs(c.cout, "#define my_syscall syscall\n");
- fputs(c.cout, "#endif\n");
-
- // Pass: forward declare all structs
- d = first_decl(c);
- loop {
- if !d {
- break;
- }
-
- if d.struct_defined {
- if d.struct_def.kind == N_UNION {
- fputs(c.cout, "union my_");
- } else {
- fputs(c.cout, "struct my_");
- }
- fputs(c.cout, d.name);
- fputs(c.cout, ";\n");
- }
-
- d = next_decl(c, d);
- }
-
- // Pass: define structs
- d = first_decl(c);
- loop {
- if !d {
- break;
- }
-
- if d.struct_defined {
- ctranslate_struct(c, d);
- }
-
- d = next_decl(c, d);
- }
-
- // Pass: define enums
- d = first_decl(c);
- has_enum = 0;
- seen = 0;
- loop {
- if !d {
- break;
- }
-
- if d.enum_defined {
- if !has_enum {
- fputs(c.cout, "enum {\n");
- has_enum = 1;
- }
- if seen {
- fputs(c.cout, ",\n");
- }
- fputs(c.cout, "\tmy_");
- fputs(c.cout, d.name);
- fputs(c.cout, " = ");
- fputd(c.cout, d.enum_value);
- seen = 1;
- }
-
- d = next_decl(c, d);
- }
- if has_enum {
- fputs(c.cout, "\n};\n");
- }
-
- // Pass: forward declare all functions
- d = first_decl(c);
- loop {
- if !d {
- break;
- }
-
- if d.func_used && d.func_defined {
- ctranslate_type(c, d.func_type, d.name, 1, d.func_decl.b.a);
- fputs(c.cout, ";\n");
- }
-
- d = next_decl(c, d);
- }
-
- // Pass: define functions
- d = first_decl(c);
- loop {
- if !d {
- break;
- }
-
- if d.func_used && d.func_defined {
- ctranslate_func(c, d);
- }
-
- d = next_decl(c, d);
- }
-
- flush_coutput(c);
-}
-
-// type <- ('void' / 'unsigned' ('long' / 'char')) declarator
-// declarator <- [*]* (ident / '(' declarator ')' '(' type (',' type)* ')')?
-
-func ctranslate_type1(c: *compiler, ty: *type, name: *byte, decl: int) {
- if ty.kind == TY_VOID {
- fputs(c.cout, "void");
- } else if ty.kind == TY_INT {
- fputs(c.cout, "unsigned long");
- } else if ty.kind == TY_BYTE {
- fputs(c.cout, "unsigned char");
- } else if ty.kind == TY_PTR {
- ctranslate_type1(c, ty.val, "", decl);
- fputs(c.cout, "*");
- } else if ty.kind == TY_FUNC {
- ctranslate_type1(c, ty.val, "", 0);
- fputs(c.cout, "(");
- if !decl {
- fputs(c.cout, "*");
- }
- } else if ty.kind == TY_STRUCT {
- fputs(c.cout, "struct my_");
- fputs(c.cout, ty.st.name);
- } else if ty.kind == TY_UNION {
- fputs(c.cout, "union my_");
- fputs(c.cout, ty.st.name);
- } else {
- die("invalid type");
- }
-}
-
-func ctranslate_type2(c: *compiler, ty: *type, name: *byte, args: *node) {
- var arg: *type;
- if ty.kind == TY_PTR {
- ctranslate_type2(c, ty.val, name, args);
- } else if ty.kind == TY_FUNC {
- ctranslate_type2(c, ty.val, name, args);
- fputs(c.cout, ")(");
- arg = ty.arg;
- if arg {
- loop {
- if args {
- ctranslate_type(c, arg.val, args.a.a.s, 0, nil);
- } else {
- ctranslate_type(c, arg.val, "", 0, nil);
- }
- arg = arg.arg;
- if arg {
- fputs(c.cout, ",");
- } else {
- break;
- }
- if args {
- args = args.b;
- }
- }
-
- } else {
- fputs(c.cout, "void");
- }
- fputs(c.cout, ")");
- } else {
- if name && name[0] {
- fputs(c.cout, " my_");
- fputs(c.cout, name);
- }
- }
-}
-
-func ctranslate_type(c: *compiler, ty: *type, name: *byte, decl: int, args: *node) {
- ctranslate_type1(c, ty, name, decl);
- ctranslate_type2(c, ty, name, args);
-}
-
-func ctranslate_zero(c: *compiler, ty: *type) {
- var n: *node;
- var v: *decl;
- var arg: *type;
- if ty.kind == TY_VOID {
- die("invalid zero void");
- } else if ty.kind == TY_INT {
- fputs(c.cout, "0");
- } else if ty.kind == TY_BYTE {
- fputs(c.cout, "0");
- } else if ty.kind == TY_PTR {
- fputs(c.cout, "0");
- } else if ty.kind == TY_FUNC {
- fputs(c.cout, "0");
- } else if ty.kind == TY_STRUCT {
- fputs(c.cout, "{");
- n = ty.st.struct_def.b;
- loop {
- if !n {
- break;
- }
- v = find(c, ty.st.name, n.a.a.s, 0);
- ctranslate_zero(c, v.member_type);
- n = n.b;
- if n {
- fputs(c.cout, ", ");
- }
- }
- fputs(c.cout, "}");
- } else if ty.kind == TY_UNION {
- fputs(c.cout, "{");
- n = ty.st.struct_def.b;
- loop {
- if !n {
- break;
- }
- v = find(c, ty.st.name, n.a.a.s, 0);
- ctranslate_zero(c, v.member_type);
- n = n.b;
- }
- fputs(c.cout, "}");
- } else {
- die("invalid type");
- }
-}
-
-func ctranslate_struct(c: *compiler, d: *decl) {
- var v: *decl;
- var n: *node;
- if d.struct_def.kind == N_UNION {
- fputs(c.cout, "union my_");
- } else {
- fputs(c.cout, "struct my_");
- }
- fputs(c.cout, d.name);
- fputs(c.cout, " {\n");
- n = d.struct_def.b;
- loop {
- if !n {
- break;
- }
-
- v = find(c, d.name, n.a.a.s, 0);
-
- fputs(c.cout, "\t");
- ctranslate_type(c, v.member_type, n.a.a.s, 0, nil);
- fputs(c.cout, ";\n");
-
- n = n.b;
- }
- fputs(c.cout, "};\n");
-}
-
-func ctranslate_vars(c: *compiler, n: *node) {
- var kind: int;
- var child: *node;
-
- if !n {
- return;
- }
-
- kind = n.kind;
- if kind == N_CONDLIST {
- loop {
- if !n {
- break;
- }
- ctranslate_vars(c, n.a.b);
- n = n.b;
- }
- } else if kind == N_STMTLIST {
- loop {
- if !n {
- break;
- }
- ctranslate_vars(c, n.a);
- n = n.b;
- }
- } else if kind == N_LOOP {
- ctranslate_vars(c, n.a);
- } else if kind == N_VARDECL {
- fputs(c.cout, "\t");
- ctranslate_type(c, n.t, n.a.s, 0, nil);
- fputs(c.cout, " = ");
- ctranslate_zero(c, n.t);
- fputs(c.cout, ";\n");
- }
-}
-
-func ctranslate_str(c: *compiler, s: *byte) {
- var i: int;
- var ch: int;
- i = 0;
- fputs(c.cout, "(unsigned char *)\"");
- loop {
- if !s[i] {
- break;
- }
-
- ch = s[i] as int;
-
- if ch < 32 || ch > 127 || ch == '\\' || ch == '"' {
- fputc(c.cout, '\\');
- fputc(c.cout, '0' + (ch >> 6) & 7);
- fputc(c.cout, '0' + (ch >> 3) & 7);
- fputc(c.cout, '0' + (ch & 7));
- } else {
- fputc(c.cout, ch);
- }
-
- i = i + 1;
- }
- fputs(c.cout, "\"");
-}
-
-func ctranslate_expr(c: *compiler, n: *node) {
- if n.kind == N_STR {
- ctranslate_str(c, n.s);
- } else if n.kind == N_NUM {
- fputd(c.cout, n.n);
- fputs(c.cout, "UL");
- } else if n.kind == N_NIL {
- fputs(c.cout, "(void *)0");
- } else if n.kind == N_CHAR {
- fputd(c.cout, n.n);
- } else if n.kind == N_CALL {
- fputs(c.cout, "(");
- ctranslate_expr(c, n.a);
- fputs(c.cout, ")");
- fputs(c.cout, "(");
- n = n.b;
- loop {
- if !n {
- break;
- }
- fputs(c.cout, "(");
- ctranslate_expr(c, n.a);
- fputs(c.cout, ")");
- n = n.b;
- if n {
- fputs(c.cout, ",");
- }
- }
- fputs(c.cout, ")");
- } else if n.kind == N_DOT {
- fputs(c.cout, "(");
- ctranslate_expr(c, n.a);
- fputs(c.cout, ")");
- if n.a.t.kind == TY_PTR {
- fputs(c.cout, "->");
- } else {
- fputs(c.cout, ".");
- }
- fputs(c.cout, "my_");
- fputs(c.cout, n.b.s);
- } else if n.kind == N_IDENT {
- fputs(c.cout, "my_");
- fputs(c.cout, n.s);
- } else if n.kind == N_ASSIGN {
- fputs(c.cout, "(");
- ctranslate_expr(c, n.a);
- fputs(c.cout, ")=(");
- ctranslate_expr(c, n.b);
- fputs(c.cout, ")");
- } else if n.kind == N_SIZEOF {
- fputd(c.cout, type_sizeof(c, n.a.t));
- fputs(c.cout, "UL");
- } else if n.kind == N_REF {
- fputs(c.cout, "&(");
- ctranslate_expr(c, n.a);
- fputs(c.cout, ")");
- } else if n.kind == N_DEREF {
- fputs(c.cout, "*(");
- ctranslate_expr(c, n.a);
- fputs(c.cout, ")");
- } else if n.kind == N_INDEX {
- fputs(c.cout, "(");
- ctranslate_expr(c, n.a);
- fputs(c.cout, ")[");
- ctranslate_expr(c, n.b);
- fputs(c.cout, "]");
- } else if n.kind == N_LT {
- fputs(c.cout, "(unsigned long)(((long)(");
- ctranslate_expr(c, n.a);
- fputs(c.cout, "))<((long)(");
- ctranslate_expr(c, n.b);
- fputs(c.cout, ")))");
- } else if n.kind == N_LE {
- fputs(c.cout, "(unsigned long)(((long)(");
- ctranslate_expr(c, n.a);
- fputs(c.cout, "))<=((long)(");
- ctranslate_expr(c, n.b);
- fputs(c.cout, ")))");
- } else if n.kind == N_GT {
- fputs(c.cout, "(unsigned long)(((long)(");
- ctranslate_expr(c, n.a);
- fputs(c.cout, "))>((long)(");
- ctranslate_expr(c, n.b);
- fputs(c.cout, ")))");
- } else if n.kind == N_GE {
- fputs(c.cout, "(unsigned long)(((long)(");
- ctranslate_expr(c, n.a);
- fputs(c.cout, "))>=((long)(");
- ctranslate_expr(c, n.b);
- fputs(c.cout, ")))");
- } else if n.kind == N_EQ {
- fputs(c.cout, "(unsigned long)(((long)(");
- ctranslate_expr(c, n.a);
- fputs(c.cout, "))==((long)(");
- ctranslate_expr(c, n.b);
- fputs(c.cout, ")))");
- } else if n.kind == N_NE {
- fputs(c.cout, "(unsigned long)(((long)(");
- ctranslate_expr(c, n.a);
- fputs(c.cout, "))!=((long)(");
- ctranslate_expr(c, n.b);
- fputs(c.cout, ")))");
- } else if n.kind == N_BNOT {
- fputs(c.cout, "(unsigned long)(!(");
- ctranslate_expr(c, n.a);
- fputs(c.cout, "))");
- } else if n.kind == N_BOR {
- fputs(c.cout, "(unsigned long)((");
- ctranslate_expr(c, n.a);
- fputs(c.cout, ")||(");
- ctranslate_expr(c, n.b);
- fputs(c.cout, "))");
- } else if n.kind == N_BAND {
- fputs(c.cout, "(unsigned long)((");
- ctranslate_expr(c, n.a);
- fputs(c.cout, ")&&(");
- ctranslate_expr(c, n.b);
- fputs(c.cout, "))");
- } else if n.kind == N_POS {
- ctranslate_expr(c, n.a);
- } else if n.kind == N_NEG {
- fputs(c.cout, "(");
- ctranslate_type(c, n.t, "", 0, nil);
- fputs(c.cout, ")(-(unsigned long)(");
- ctranslate_expr(c, n.a);
- fputs(c.cout, "))");
- } else if n.kind == N_NOT {
- fputs(c.cout, "(");
- ctranslate_type(c, n.t, "", 0, nil);
- fputs(c.cout, ")(~(unsigned long)(");
- ctranslate_expr(c, n.a);
- fputs(c.cout, "))");
- } else if n.kind == N_ADD {
- fputs(c.cout, "(");
- ctranslate_type(c, n.t, "", 0, nil);
- fputs(c.cout, ")(((unsigned long)(");
- ctranslate_expr(c, n.a);
- fputs(c.cout, "))+((unsigned long)(");
- ctranslate_expr(c, n.b);
- fputs(c.cout, ")))");
- } else if n.kind == N_SUB {
- fputs(c.cout, "(");
- ctranslate_type(c, n.t, "", 0, nil);
- fputs(c.cout, ")(((unsigned long)(");
- ctranslate_expr(c, n.a);
- fputs(c.cout, "))-((unsigned long)(");
- ctranslate_expr(c, n.b);
- fputs(c.cout, ")))");
- } else if n.kind == N_MUL {
- fputs(c.cout, "(");
- ctranslate_type(c, n.t, "", 0, nil);
- fputs(c.cout, ")(((long)(");
- ctranslate_expr(c, n.a);
- fputs(c.cout, "))*((long)(");
- ctranslate_expr(c, n.b);
- fputs(c.cout, ")))");
- } else if n.kind == N_DIV {
- fputs(c.cout, "(");
- ctranslate_type(c, n.t, "", 0, nil);
- fputs(c.cout, ")(((long)(");
- ctranslate_expr(c, n.a);
- fputs(c.cout, "))/((long)(");
- ctranslate_expr(c, n.b);
- fputs(c.cout, ")))");
- } else if n.kind == N_MOD {
- fputs(c.cout, "(");
- ctranslate_type(c, n.t, "", 0, nil);
- fputs(c.cout, ")(((long)(");
- ctranslate_expr(c, n.a);
- fputs(c.cout, "))%((long)(");
- ctranslate_expr(c, n.b);
- fputs(c.cout, ")))");
- } else if n.kind == N_LSH {
- fputs(c.cout, "(");
- ctranslate_type(c, n.t, "", 0, nil);
- fputs(c.cout, ")(((unsigned long)(");
- ctranslate_expr(c, n.a);
- fputs(c.cout, "))<<((unsigned long)(");
- ctranslate_expr(c, n.b);
- fputs(c.cout, ")))");
- } else if n.kind == N_RSH {
- fputs(c.cout, "(");
- ctranslate_type(c, n.t, "", 0, nil);
- fputs(c.cout, ")(((unsigned long)(");
- ctranslate_expr(c, n.a);
- fputs(c.cout, "))>>((unsigned long)(");
- ctranslate_expr(c, n.b);
- fputs(c.cout, ")))");
- } else if n.kind == N_AND {
- fputs(c.cout, "(");
- ctranslate_type(c, n.t, "", 0, nil);
- fputs(c.cout, ")(((unsigned long)(");
- ctranslate_expr(c, n.a);
- fputs(c.cout, "))&((unsigned long)(");
- ctranslate_expr(c, n.b);
- fputs(c.cout, ")))");
- } else if n.kind == N_OR {
- fputs(c.cout, "(");
- ctranslate_type(c, n.t, "", 0, nil);
- fputs(c.cout, ")(((unsigned long)(");
- ctranslate_expr(c, n.a);
- fputs(c.cout, "))|((unsigned long)(");
- ctranslate_expr(c, n.b);
- fputs(c.cout, ")))");
- } else if n.kind == N_XOR {
- fputs(c.cout, "(");
- ctranslate_type(c, n.t, "", 0, nil);
- fputs(c.cout, ")(((unsigned long)(");
- ctranslate_expr(c, n.a);
- fputs(c.cout, "))^((unsigned long)(");
- ctranslate_expr(c, n.b);
- fputs(c.cout, ")))");
- } else if n.kind == N_CAST {
- fputs(c.cout, "(");
- ctranslate_type(c, n.t, "", 0, nil);
- fputs(c.cout, ")");
- ctranslate_expr(c, n.a);
- } else {
- die("invalid expr");
- }
-}
-
-func ctranslate_stmt(c: *compiler, n: *node) {
- var kind: int;
- var child: *node;
-
- if !n {
- return;
- }
-
- kind = n.kind;
- if kind == N_CONDLIST {
- fputs(c.cout, "\t");
- loop {
- fputs(c.cout, "if (");
-
- ctranslate_expr(c, n.a.a);
-
- fputs(c.cout, ") {\n");
-
- ctranslate_stmt(c, n.a.b);
-
- n = n.b;
-
- fputs(c.cout, "\t}");
-
- if !n {
- fputs(c.cout, "\n");
- break;
- }
-
- fputs(c.cout, " else ");
-
- if !n.a.a {
- fputs(c.cout, "{\n");
- ctranslate_stmt(c, n.a.b);
- fputs(c.cout, "\t}\n");
- break;
- }
- }
- } else if kind == N_STMTLIST {
- loop {
- if !n {
- break;
- }
-
- ctranslate_stmt(c, n.a);
-
- n = n.b;
- }
- } else if kind == N_LOOP {
- fputs(c.cout, "\twhile (1) {\n");
- ctranslate_stmt(c, n.a);
- fputs(c.cout, "\t}\n");
- } else if kind == N_BREAK {
- fputs(c.cout, "\tbreak;\n");
- } else if kind == N_CONTINUE {
- fputs(c.cout, "\tcontinue;\n");
- } else if kind == N_RETURN {
- fputs(c.cout, "\treturn");
- if n.a {
- fputs(c.cout, " ");
- ctranslate_expr(c, n.a);
- }
- fputs(c.cout, ";\n");
- } else if kind == N_LABEL {
- fputs(c.cout, "my_");
- fputs(c.cout, n.a.s);
- fputs(c.cout, ":\n");
- } else if kind == N_GOTO {
- fputs(c.cout, "\tgoto ");
- fputs(c.cout, "my_");
- fputs(c.cout, n.a.s);
- fputs(c.cout, ";\n");
- } else if kind != N_VARDECL {
- fputs(c.cout, "\t");
- ctranslate_expr(c, n);
- fputs(c.cout, ";\n");
- }
-}
-
-func ctranslate_func(c: *compiler, d: *decl) {
- var n: *node;
- var ty: *type;
- if d.func_def {
- ctranslate_type(c, d.func_type, d.name, 1, d.func_def.a.b.a);
- fputs(c.cout, "{\n");
- ctranslate_vars(c, d.func_def.b);
- ctranslate_stmt(c, d.func_def.b);
- fputs(c.cout, "}\n");
- }
-}
diff --git a/attic/ed25519_test.om b/attic/ed25519_test.om
@@ -1,22 +0,0 @@
-main(argc: int, argv: **byte, envp: **byte) {
- var _a: _ed25519_point;
- var a: *byte;
- var _b: _ed25519_point;
- var b: *byte;
- var _c: _ed25519_point;
- var c: *byte;
-
- a = (&_a):*byte;
- b = (&_b):*byte;
- c = (&_c):*byte;
-
- assert(unhex(a, "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60") == 32, "unhex");
- ed25519_sign(c, a, "", 0);
- fdxxd(1, c, 64);
- fdputc(1, '\n');
-
- assert(unhex(a, "4ccd089b28ff96da9db6c346ec114e0f5b8a319f35aba624da8cf6ed4fb8a6fb") == 32, "unhex");
- ed25519_sign(c, a, "r", 1);
- fdxxd(1, c, 64);
- fdputc(1, '\n');
-}
diff --git a/attic/genlex.om b/attic/genlex.om
@@ -1,1115 +0,0 @@
-func getchar(): int {
- var b: byte;
- var ret: int;
- ret = read(0, &b, 1);
- if (ret < 0) {
- exit(3);
- }
- if (ret == 0) {
- return -1;
- }
- return b as int;
-}
-
-func putchar(ch: int): void {
- var b: byte;
- var ret: int;
- b = ch as byte;
- ret = write(1, &b, 1);
- if (ret != 1) {
- exit(3);
- }
-}
-
-struct compiler {
- a: alloc;
- nc: int;
- lineno: int;
- colno: int;
- tt: int;
- n: *nfa;
- buf: *byte;
- tlen: int;
- tmax: int;
- tags: *tag;
- ntags: int;
- nnfa: int;
- ndfa: int;
- d: *dfa;
-}
-
-func setup(c: *compiler): void {
- setup_alloc(&c.a);
- c.nc = getchar();
- c.lineno = 1;
- c.colno = 1;
- c.tt = 0;
- c.n = nil;
- c.tmax = 256;
- c.tlen = 0;
- c.buf = alloc(&c.a, c.tmax);
- c.tags = nil;
- c.ntags = 0;
- c.nnfa = 0;
- c.ndfa = 0;
- c.d = nil;
- feed(c);
-}
-
-func feedc(c: *compiler): void {
- c.nc = getchar();
- if (c.nc == '\n') {
- c.lineno = c.lineno + 1;
- c.colno = 0;
- }
- c.colno = c.colno +1;
-}
-
-enum {
- T_EOF,
- T_IDENT,
- T_LITERAL,
- T_CHARSET,
- T_DOT,
- T_STAR,
- T_PLUS,
- T_QMARK,
- T_LPAR,
- T_RPAR,
- T_ALT,
- T_EQUALS,
- T_SEMI,
-}
-
-func feed(c: *compiler): void {
- c.n = nil;
- c.tlen = 0;
-
- loop {
- if (c.nc == -1) {
- c.tt = T_EOF;
- return;
- } else if (c.nc == ' ' || c.nc == '\t' || c.nc == '\r' || c.nc == '\n') {
- feedc(c);
- } else if (c.nc == '/') {
- feedc(c);
- if (c.nc == '/') {
- loop {
- if (c.nc == '\n' || c.nc == -1) {
- break;
- }
- feedc(c);
- }
- } else {
- die("slash but a comment");
- }
- } else {
- break;
- }
- }
-
- if ((c.nc >= 'a' && c.nc <= 'z') || (c.nc >= 'A' && c.nc <= 'Z') || c.nc == '_') {
- feed_ident(c);
- } else if (c.nc == '"') {
- feed_literal(c);
- } else if (c.nc == '[') {
- feed_charset(c);
- } else if (c.nc == '.') {
- c.tt = T_DOT;
- feedc(c);
- } else if (c.nc == '*') {
- c.tt = T_STAR;
- feedc(c);
- } else if (c.nc == '+') {
- c.tt = T_PLUS;
- feedc(c);
- } else if (c.nc == '?') {
- c.tt = T_QMARK;
- feedc(c);
- } else if (c.nc == '(') {
- c.tt = T_LPAR;
- feedc(c);
- } else if (c.nc == ')') {
- c.tt = T_RPAR;
- feedc(c);
- } else if (c.nc == '|') {
- c.tt = T_ALT;
- feedc(c);
- } else if (c.nc == '=') {
- c.tt = T_EQUALS;
- feedc(c);
- } else if (c.nc == ';') {
- c.tt = T_SEMI;
- feedc(c);
- } else {
- die("invalid char");
- }
-}
-
-func feed_ident(c: *compiler): void {
- c.tt = T_IDENT;
- loop {
- if (!((c.nc >= 'a' && c.nc <= 'z') ||
- (c.nc >= 'A' && c.nc <= 'Z') ||
- (c.nc >= '0' && c.nc <= '9') ||
- c.nc == '_')) {
- break;
- }
-
- c.buf[c.tlen] = c.nc as byte;
- c.tlen = c.tlen + 1;
- if (c.tlen == c.tmax) {
- die("ident too long");
- }
- c.buf[c.tlen] = 0 as byte;
-
- feedc(c);
- }
-}
-
-func hexdig(c: *compiler): int {
- if (c.nc >= '0' && c.nc <= '9') {
- return c.nc - '0';
- }
-
- if (c.nc >= 'A' && c.nc <= 'F') {
- return (c.nc - 'A') + 10;
- }
-
- if (c.nc >= 'a' && c.nc <= 'f') {
- return (c.nc - 'a') + 10;
- }
-
- die("invalid hex digit");
-}
-
-func feed_escape(c: *compiler): void {
- var hex: int;
-
- feedc(c);
-
- if (c.nc == 't') {
- c.nc = '\t';
- } else if (c.nc == 'r') {
- c.nc = '\r';
- } else if (c.nc == 'n') {
- c.nc = '\n';
- } else if (c.nc == '\\') {
- c.nc = '\\';
- } else if (c.nc == '\'') {
- c.nc = '\'';
- } else if (c.nc == '\"') {
- c.nc = '\"';
- } else if (c.nc == '-') {
- c.nc = '-';
- } else if (c.nc == '[') {
- c.nc = '[';
- } else if (c.nc == ']') {
- c.nc = ']';
- } else if (c.nc == 'x') {
- feedc(c);
- hex = hexdig(c) * 16;
- feedc(c);
- hex = hex + hexdig(c);
- c.nc = hex;
- } else {
- die("invalid escape");
- }
-}
-
-func feed_literal(c: *compiler): void {
- var a: *nfa;
-
- c.tt = T_LITERAL;
- c.n = nfa_empty(c);
-
- feedc(c);
-
- loop {
- if (c.nc == '"') {
- feedc(c);
- return;
- }
-
- if (c.nc == -1 || c.nc == 0 || c.nc == '\n') {
- die("invalid char in literal");
- }
-
- if (c.nc == '\\') {
- feed_escape(c);
- }
-
- a = nfa_literal(c, c.nc as byte);
- c.n = nfa_concat(c, c.n, a);
-
- feedc(c);
- }
-}
-
-func feed_charset(c: *compiler): void {
- var left: int;
- var right: int;
- var mode: int;
- var nonempty: int;
- var i: int;
- var a: *nfa;
-
- c.tt = T_CHARSET;
-
- feedc(c);
-
- mode = 1;
- nonempty = 0;
-
- i = left;
- loop {
- if (i == 256) {
- break;
- }
- c.buf[i] = 0 as byte;
- i = i + 1;
- }
-
- loop {
- if (c.nc == ']') {
- feedc(c);
- break;
- }
-
- if (c.nc == -1 || c.nc == 0 || c.nc == '\n' || c.nc == '-') {
- die("invalid char in charset");
- }
-
- if (c.nc == '^') {
- if (!mode) {
- die("invalid char in charset");
- }
-
- feedc(c);
- if (mode && !nonempty) {
- i = 0;
- loop {
- if (i == 256) {
- break;
- }
- c.buf[i] = 1 as byte;
- i = i + 1;
- }
- }
- mode = 0;
- continue;
- }
-
- if (c.nc == '\\') {
- feed_escape(c);
- left = c.nc;
- feedc(c);
- } else {
- left = c.nc;
- feedc(c);
- }
-
- if (c.nc == '-') {
- feedc(c);
-
- if (c.nc == -1 || c.nc == 0 || c.nc == '\n' || c.nc == '-') {
- die("invalid char in charset");
- }
-
- if (c.nc == '\\') {
- feed_escape(c);
- right = c.nc + 1;
- feedc(c);
- } else {
- right = c.nc + 1;
- feedc(c);
- }
- } else {
- right = left + 1;
- }
-
- nonempty = 1;
- i = left;
- loop {
- if (i >= right) {
- break;
- }
- c.buf[i] = mode as byte;
- i = i + 1;
- }
- }
-
- c.n = nfa_empty(c);
- c.n.left = 256;
- c.n.right = 256;
-
- i = 0;
- loop {
- loop {
- if (i == 256) {
- left = 256;
- break;
- }
-
- if (c.buf[i]) {
- left = i;
- break;
- }
-
- i = i + 1;
- }
-
- loop {
- if (i == 256) {
- right = 256;
- break;
- }
-
- if (!c.buf[i]) {
- right = i;
- break;
- }
-
- i = i + 1;
- }
-
- if (left >= right) {
- break;
- }
-
- a = nfa_empty(c);
- a.left = left;
- a.right = right;
-
- c.n = nfa_alt(c, c.n, a);
- }
-}
-
-func parse_ident(c: *compiler): *tag {
- var t: *tag;
- if (c.tt != T_IDENT) {
- return nil;
- }
- t = find_tag(c, c.buf);
- feed(c);
- return t;
-}
-
-struct tag {
- next: *tag;
- s: *byte;
- id: int;
-}
-
-func intern(c: *compiler): *byte {
- var s: *byte;
- var i: int;
- s = alloc(&c.a, c.tlen + 1);
- i = 0;
- loop {
- if (i == c.tlen) {
- break;
- }
- s[i] = c.buf[i];
- i = i + 1;
- }
- s[c.tlen] = 0 as byte;
- return s;
-}
-
-func find_tag(c: *compiler, s: *byte): *tag {
- var t: *tag;
- var link: **tag;
- link = &c.tags;
- loop {
- t = *link;
- if (!t) {
- break;
- }
- if (!strcmp(t.s, s)) {
- return t;
- }
- link = &t.next;
- }
- t = alloc(&c.a, sizeof(*t)) as *tag;
- t.next = nil;
- t.s = intern(c);
- t.id = c.ntags;
- c.ntags = c.ntags + 1;
- *link = t;
- return t;
-}
-
-struct nfa {
- id: int;
- tag: *tag;
- left: int;
- right: int;
- live: int;
- a: *nfa;
- b: *nfa;
- end: *nfa;
-}
-
-func nfa_empty(c: *compiler): *nfa {
- var n: *nfa;
- n = alloc(&c.a, sizeof(*n)) as *nfa;
- n.id = c.nnfa;
- n.left = -1;
- n.right = -1;
- n.live = 0;
- n.a = nil;
- n.b = nil;
- n.end = n;
- c.nnfa = c.nnfa + 1;
- return n;
-}
-
-func nfa_literal(c: *compiler, a: byte): *nfa {
- var n: *nfa;
- n = nfa_empty(c);
- n.left = a as int;
- n.right = n.left + 1;
- return n;
-}
-
-func nfa_alt(c: *compiler, a: *nfa, b: *nfa): *nfa {
- var i: *nfa;
- var o: *nfa;
- i = nfa_empty(c);
- o = nfa_empty(c);
- i.a = a;
- i.b = b;
- i.end = o;
- a.end.a = o;
- b.end.a = o;
- return i;
-}
-
-func nfa_concat(c: *compiler, a: *nfa, b: *nfa): *nfa {
- a.end.a = b;
- a.end = b.end;
- return a;
-}
-
-func nfa_plus(c: *compiler, a: *nfa): *nfa {
- var o: *nfa;
- o = nfa_empty(c);
- o.b = a;
- a.end.a = o;
- a.end = o;
- return a;
-}
-
-func nfa_qmark(c: *compiler, a: *nfa): *nfa {
- var b: *nfa;
- b = nfa_empty(c);
- a = nfa_alt(c, a, b);
- return a;
-}
-
-func nfa_star(c: *compiler, a: *nfa): *nfa {
- a = nfa_plus(c, a);
- a = nfa_qmark(c, a);
- return a;
-}
-
-func parse_literal(c: *compiler): *nfa {
- var n: *nfa;
- if (c.tt != T_LITERAL) {
- return nil;
- }
- n = c.n;
- feed(c);
- return n;
-}
-
-func parse_charset(c: *compiler): *nfa {
- var n: *nfa;
- if (c.tt != T_CHARSET) {
- return nil;
- }
- n = c.n;
- feed(c);
- return n;
-}
-
-func parse_dot(c: *compiler): *nfa {
- var n: *nfa;
- if (c.tt != T_DOT) {
- return nil;
- }
- feed(c);
- n = nfa_empty(c);
- n.left = 0;
- n.right = 256;
- return n;
-}
-
-// primary := literal
-// | charset
-// | dot
-// | '(' regex ')'
-func parse_primary(c: *compiler): *nfa {
- var n: *nfa;
-
- n = parse_literal(c);
- if (n) {
- return n;
- }
-
- n = parse_charset(c);
- if (n) {
- return n;
- }
-
- n = parse_dot(c);
- if (n) {
- return n;
- }
-
- if (c.tt == T_LPAR) {
- feed(c);
-
- n = parse_regex(c);
-
- if (c.tt != T_RPAR) {
- die("expected )");
- }
- feed(c);
-
- return n;
- }
-
- return nil;
-}
-
-// post := primary
-// | post '*'
-// | post '+'
-// | post '?'
-func parse_post(c: *compiler): *nfa {
- var n: *nfa;
-
- n = parse_primary(c);
- if (!n) {
- return nil;
- }
-
- loop {
- if (c.tt == T_STAR) {
- n = nfa_star(c, n);
- feed(c);
- } else if (c.tt == T_PLUS) {
- n = nfa_plus(c, n);
- feed(c);
- } else if (c.tt == T_QMARK) {
- n = nfa_qmark(c, n);
- feed(c);
- } else {
- return n;
- }
- }
-}
-
-// concat := post
-// | post concat
-func parse_concat(c: *compiler): *nfa {
- var n: *nfa;
- var b: *nfa;
-
- n = parse_post(c);
- if (!n) {
- return nil;
- }
-
- loop {
- b = parse_post(c);
- if (!b) {
- return n;
- }
-
- n = nfa_concat(c, n, b);
- }
-}
-
-// regex := concat
-// | '|' regex
-// | concat '|' regex
-func parse_regex(c: *compiler): *nfa {
- var n: *nfa;
- var b: *nfa;
-
- n = parse_concat(c);
- if (!n) {
- n = nfa_empty(c);
- }
-
- loop {
- if (c.tt != T_ALT) {
- return n;
- }
- feed(c);
-
- b = parse_concat(c);
- if (!b) {
- b = nfa_empty(c);
- }
-
- n = nfa_alt(c, n, b);
- }
-}
-
-// decl := ident '=' regex ';'
-func parse_decl(c: *compiler): *nfa {
- var regex: *nfa;
- var t: *tag;
- var n: *nfa;
-
- t = parse_ident(c);
- if (!t) {
- return nil;
- }
-
- if (c.tt != T_EQUALS) {
- die("expected =");
- }
- feed(c);
-
- regex = parse_regex(c);
-
- if (c.tt != T_SEMI) {
- die("expected ;");
- }
- feed(c);
-
- n = nfa_empty(c);
- n.tag = t;
-
- return nfa_concat(c, regex, n);
-}
-
-// progam := decl
-// | decl program
-func parse_program(c: *compiler): *nfa {
- var n: *nfa;
- var p: *nfa;
-
- p = nil;
- loop {
- n = parse_decl(c);
- if (!n) {
- if (c.tt != T_EOF) {
- die("expected eof");
- }
- return p;
- }
-
- if (p) {
- p = nfa_alt(c, p, n);
- } else {
- p = n;
- }
- }
-}
-
-struct dfa {
- id: int;
- link: **dfa;
- key: nlist;
- l: *dfa;
- r: *dfa;
- seen: int;
-}
-
-struct nlist {
- live: **nfa;
- fill: int;
- cap: int;
- tag: *tag;
-}
-
-func alloc_nlist(c: *compiler, l: *nlist, cap: int): void {
- l.cap = cap;
- l.live = alloc(&c.a, sizeof(*l.live) * cap) as **nfa;
- l.fill = 0;
- l.tag = nil;
-}
-
-func activate(l: *nlist, n: *nfa): void {
- if (n.live) {
- return;
- }
-
- n.live = 1;
-
- l.live[l.fill] = n;
- l.fill = l.fill + 1;
-
- if (n.left == -1) {
- if ((!l.tag) || (n.tag && n.tag.id < l.tag.id)) {
- l.tag = n.tag;
- }
-
- if (n.a) {
- activate(l, n.a);
- }
-
- if (n.b) {
- activate(l, n.b);
- }
- }
-}
-
-func nlist_cmp(a: *nlist, b: *nlist): int {
- var i: int;
-
- i = 0;
- loop {
- if (i == a.fill && i == b.fill) {
- break;
- }
-
- if (i == a.fill) {
- return -1;
- }
-
- if (i == b.fill) {
- return 1;
- }
-
- if (a.live[i].id > b.live[i].id) {
- return 1;
- }
-
- if (a.live[i].id < b.live[i].id) {
- return -1;
- }
-
- i = i + 1;
- }
-
- if (!a.tag && !b.tag) {
- return 0;
- }
-
- if (!a.tag) {
- return -1;
- }
-
- if (!b.tag) {
- return 1;
- }
-
- if (a.tag.id < b.tag.id) {
- return -1;
- }
-
- if (a.tag.id > b.tag.id) {
- return 1;
- }
-
- return 0;
-}
-
-func nlist_sort(l: *nlist): void {
- var i: int;
- var j: int;
- var k: int;
- var tmp: *nfa;
-
- if (l.fill < 2) {
- return;
- }
-
- i = l.fill - 1;
- loop {
- j = i;
- loop {
- k = (j << 1) + 1;
- if (k >= l.fill) {
- break;
- }
- if (k + 1 < l.fill && l.live[k].id < l.live[k + 1].id) {
- k = k + 1;
- }
- if (l.live[j].id >= l.live[k].id) {
- break;
- }
- tmp = l.live[k];
- l.live[k] = l.live[j];
- l.live[j] = tmp;
- j = k;
- }
- if (i == 0) {
- break;
- }
- i = i - 1;
- }
-
- i = l.fill - 1;
- loop {
- if (i == 0) {
- break;
- }
- tmp = l.live[i];
- l.live[i] = l.live[0];
- j = 0;
- loop {
- k = (j << 1) + 1;
- if (k >= i) {
- break;
- }
- if (k + 1 < i && l.live[k].id < l.live[k + 1].id) {
- k = k + 1;
- }
- if (tmp.id >= l.live[k].id) {
- break;
- }
- j = k;
- }
- l.live[j] = tmp;
- i = i - 1;
- }
-}
-
-func alloc_link(c: *compiler): **dfa {
- var link: **dfa;
- var i: int;
- link = alloc(&c.a, sizeof(*link) * 256) as **dfa;
- i = 0;
- loop {
- if (i == 256) {
- break;
- }
- link[i] = nil;
- i = i + 1;
- }
- return link;
-}
-
-func nlist_copy(c: *compiler, dest: *nlist, src: *nlist): void {
- var i: int;
- alloc_nlist(c, dest, src.fill);
- dest.fill = src.fill;
- dest.tag = src.tag;
- i = 0;
- loop {
- if (i >= src.fill) {
- break;
- }
- dest.live[i] = src.live[i];
- i = i + 1;
- }
-}
-
-func nlist2dfa(c: *compiler, l: *nlist): *dfa {
- var link: **dfa;
- var d: *dfa;
- var n: *nfa;
- var t: *tag;
- var dir: int;
- var i: int;
- var j: int;
-
- if (l.fill == 0 && !l.tag) {
- return nil;
- }
-
- link = &c.d;
- loop {
- d = *link;
- if (!d) {
- break;
- }
-
- dir = nlist_cmp(l, &d.key);
-
- if (dir < 0) {
- link = &d.l;
- } else if (dir > 0) {
- link = &d.r;
- } else {
- return d;
- }
- }
-
- d = alloc(&c.a, sizeof(*d)) as *dfa;
- d.id = c.ndfa;
- d.link = alloc_link(c);
- nlist_copy(c, &d.key, l);
- d.l = nil;
- d.r = nil;
- d.seen = 0;
-
- c.ndfa = c.ndfa + 1;
-
- *link = d;
-
- i = 0;
- loop {
- if (i == 256) {
- break;
- }
-
- deactivate(l);
- j = 0;
- loop {
- if (j >= d.key.fill) {
- break;
- }
-
- n = d.key.live[j];
- if (n.left <= i && i < n.right) {
- if (n.a) {
- activate(l, n.a);
- }
- if (n.b) {
- activate(l, n.b);
- }
- }
-
- j = j + 1;
- }
-
- d.link[i] = nlist2dfa(c, l);
-
- i = i + 1;
- }
-
- return d;
-}
-
-func deactivate(l: *nlist): void {
- var i: int;
- i = 0;
- loop {
- if (i >= l.fill) {
- l.fill = 0;
- l.tag = nil;
- break;
- }
- l.live[i].live = 0;
- i = i + 1;
- }
-}
-
-func powerset(c: *compiler, n: *nfa): *dfa {
- var live: nlist;
- alloc_nlist(c, &live, c.nnfa);
- activate(&live, n);
- return nlist2dfa(c, &live);
-}
-
-func codegen(c: *compiler, a: *dfa): void {
- var i: int;
- var b: *dfa;
- var lo: int;
- var hi: int;
-
- if (a.seen) {
- return;
- }
- a.seen = 1;
-
- fdputs(1, ":_");
- fdputd(1, a.id);
- fdputs(1, ";\n");
-
- if (a.key.tag) {
- fdputs(1, "\tlexmark(l, T_");
- fdputs(1, a.key.tag.s);
- fdputs(1, ");\n");
- }
-
- fdputs(1, "\tch = lexfeedc(l);\n");
-
- i = 0;
- loop {
- loop {
- if (i == 256 || a.link[i]) {
- lo = i;
- break;
- }
- i = i + 1;
- }
-
- if (lo == 256) {
- break;
- }
-
- b = a.link[i];
-
- loop {
- if (i == 256 || a.link[i] != b) {
- hi = i;
- break;
- }
- i = i + 1;
- }
-
- if (lo != (hi - 1)) {
- fdputs(1, "\tif (ch >= ");
- fdputd(1, lo);
- fdputs(1, " && ch <= ");
- fdputd(1, hi - 1);
- } else {
- fdputs(1, "\tif (ch == ");
- fdputd(1, lo);
- }
- fdputs(1, ") { ");
- fdputs(1, "goto _");
- fdputd(1, b.id);
- fdputs(1, "; }\n");
-
- }
-
- fdputs(1, "\treturn;\n");
-
- i = 0;
- loop {
- if (i == 256) {
- break;
- }
-
- if (a.link[i]) {
- codegen(c, a.link[i]);
- }
-
- i = i + 1;
- }
-}
-
-func gen(c: *compiler, a: *dfa): void {
- var t: *tag;
- t = c.tags;
- fdputs(1, "enum {\n");
- fdputs(1, "\tT_INVALID,\n");
- fdputs(1, "\tT_EOF,\n");
- loop {
- if (!t) {
- break;
- }
- fdputs(1, "\tT_");
- fdputs(1, t.s);
- fdputs(1, ",\n");
- t = t.next;
- }
- fdputs(1, "}\n");
- fdputs(1, "\n");
- fdputs(1, "lexstep(l: *lex_state): void {\n");
- fdputs(1, "\tvar ch: int;\n");
- fdputs(1, "\tlexmark(l, T_INVALID);\n");
- codegen(c, a);
- fdputs(1, "}\n");
-}
-
-func main(argc: int, argv: **byte, envp: **byte): void {
- var c: compiler;
- var n: *nfa;
- var a: *dfa;
- setup(&c);
- n = parse_program(&c);
- a = powerset(&c, n);
- gen(&c, a);
-}
diff --git a/attic/lex1.om b/attic/lex1.om
@@ -1,438 +0,0 @@
-struct lexer {
- a: *alloc;
- in: *file;
- nc: int;
- filename: *byte;
- lineno: int;
- colno: int;
- tt: int;
- token: *byte;
- tlen: int;
- tmax: int;
-}
-
-enum {
- T_EOF,
- T_IDENT,
- T_NUM,
- T_HEX,
- T_STR,
- T_CHAR,
- T_LPAR,
- T_RPAR,
- T_LBRA,
- T_RBRA,
- T_COMMA,
- T_SEMI,
- T_COLON,
- T_STAR,
- T_DOT,
- T_NOT,
- T_ASSIGN,
- T_AMP,
- T_OR,
- T_XOR,
- T_LT,
- T_GT,
- T_LE,
- T_GE,
- T_EQ,
- T_NE,
- T_ADD,
- T_SUB,
- T_LSH,
- T_RSH,
- T_BANG,
- T_BOR,
- T_BAND,
- T_LSQ,
- T_RSQ,
- T_DIV,
- T_MOD,
-}
-
-setup_lexer(a: *alloc): *lexer {
- var c: *lexer;
-
- c = alloc(a, sizeof(*c)):*lexer;
-
- c.a = a;
-
- c.in = 0: *file;
- c.nc = 0;
- c.filename = 0:*byte;
- c.lineno = 1;
- c.colno = 1;
- c.tlen = 0;
- c.tmax = 4096;
- c.token = alloc(c.a, c.tmax);
- c.tt = 0;
-
- return c;
-}
-
-lshow_context(c: *lexer) {
- fdputs(2, "on ");
- if (c.filename) {
- fdputs(2, c.filename);
- }
- fdputs(2, ":");
- fdputd(2, c.lineno);
- fdputs(2, ":");
- fdputd(2, c.colno);
- fdputs(2, "\n");
-}
-
-ldie(c: *lexer, msg: *byte) {
- lshow_context(c);
- fdputs(2, "cdie: ");
- fdputs(2, msg);
- fdputs(2, "\n");
- exit(1);
-}
-
-open_source(c: *lexer, filename: *byte) {
- var fd: int;
-
- c.filename = filename;
- c.nc = 0;
- c.lineno = 1;
- c.colno = 1;
- c.tlen = 0;
- c.tt = 0;
-
- fd = open(filename, 0, 0);
- if (fd < 0) {
- ldie(c, "failed to open file");
- }
-
- c.in = fopen(fd, c.a);
- c.nc = fgetc(c.in);
-
- feed(c);
-}
-
-close_source(c: *lexer) {
- if (c.in) {
- fclose(c.in);
- }
- c.in = 0: *file;
-}
-
-feedc(c: *lexer) {
- c.nc = fgetc(c.in);
- if (c.nc == '\n') {
- c.lineno = c.lineno + 1;
- c.colno = 0;
- }
- c.colno = c.colno + 1;
-}
-
-tappend(c: *lexer) {
- c.token[c.tlen] = c.nc:byte;
- c.tlen = c.tlen + 1;
- if (c.tlen == c.tmax) {
- ldie(c, "identifier too long");
- }
- c.token[c.tlen] = 0:byte;
- feedc(c);
-}
-
-feed(c: *lexer) {
- c.tlen = 0;
- c.token[0] = 0:byte;
-
- loop {
- if (c.nc == -1) {
- // Reached the end of input
- c.tt = T_EOF;
- return;
- } else if (c.nc == ' ' || c.nc == '\t' || c.nc == '\r') {
- // Whitespace
- feedc(c);
- } else if (c.nc == '\n') {
- // Line end
- feedc(c);
- } else if (c.nc == '/') {
- // Comment
- feedc(c);
- if (c.nc == '/') {
- // Read until the end of the comment
- loop {
- if (c.nc == '\n' || c.nc == -1) {
- break;
- }
- feedc(c);
- }
- } else {
- c.tt = T_DIV;
- return;
- }
-
- } else {
- // Start of a real token
- break;
- }
- }
-
- // Identifier
- if ((c.nc >= 'a' && c.nc <= 'z') || (c.nc >= 'A' && c.nc <= 'Z') || c.nc == '_') {
- feed_ident(c);
- return;
- }
-
- // String
- if (c.nc == '"') {
- feed_str(c);
- return;
- }
-
- // Character
- if (c.nc == '\'') {
- feed_char(c);
- return;
- }
-
- // Number
- if (c.nc >= '0' && c.nc <= '9') {
- feed_num(c);
- return;
- }
-
- // Single character tokens
- if (c.nc == '(') {
- c.tt = T_LPAR;
- feedc(c);
- } else if (c.nc == ')') {
- c.tt = T_RPAR;
- feedc(c);
- } else if (c.nc == '{') {
- c.tt = T_LBRA;
- feedc(c);
- } else if (c.nc == '}') {
- c.tt = T_RBRA;
- feedc(c);
- } else if (c.nc == ',') {
- c.tt = T_COMMA;
- feedc(c);
- } else if (c.nc == ';') {
- c.tt = T_SEMI;
- feedc(c);
- } else if (c.nc == ':') {
- c.tt = T_COLON;
- feedc(c);
- } else if (c.nc == '*') {
- c.tt = T_STAR;
- feedc(c);
- } else if (c.nc == '.') {
- c.tt = T_DOT;
- feedc(c);
- } else if (c.nc == '=') {
- c.tt = T_ASSIGN;
- feedc(c);
- if (c.nc == '=') {
- c.tt = T_EQ;
- feedc(c);
- }
- } else if (c.nc == '&') {
- c.tt = T_AMP;
- feedc(c);
- if (c.nc == '&') {
- c.tt = T_BAND;
- feedc(c);
- }
- } else if (c.nc == '~') {
- c.tt = T_NOT;
- feedc(c);
- } else if (c.nc == '|') {
- c.tt = T_OR;
- feedc(c);
- if (c.nc == '|') {
- c.tt = T_BOR;
- feedc(c);
- }
- } else if (c.nc == '^') {
- c.tt = T_XOR;
- feedc(c);
- } else if (c.nc == '!') {
- c.tt = T_BANG;
- feedc(c);
- if (c.nc == '=') {
- c.tt = T_NE;
- feedc(c);
- }
- } else if (c.nc == '<') {
- c.tt = T_LT;
- feedc(c);
- if (c.nc == '<') {
- c.tt = T_LSH;
- feedc(c);
- } else if (c.nc == '=') {
- c.tt = T_LE;
- feedc(c);
- }
- } else if (c.nc == '>') {
- c.tt = T_GT;
- feedc(c);
- if (c.nc == '>') {
- c.tt = T_RSH;
- feedc(c);
- } else if (c.nc == '=') {
- c.tt = T_GE;
- feedc(c);
- }
- } else if (c.nc == '[') {
- c.tt = T_LSQ;
- feedc(c);
- } else if (c.nc == ']') {
- c.tt = T_RSQ;
- feedc(c);
- } else if (c.nc == '+') {
- c.tt = T_ADD;
- feedc(c);
- } else if (c.nc == '-') {
- c.tt = T_SUB;
- feedc(c);
- } else if (c.nc == '%') {
- c.tt = T_MOD;
- feedc(c);
- } else {
- ldie(c, "invalid char");
- }
-}
-
-feed_ident(c: *lexer) {
- c.tt = T_IDENT;
- loop {
- if (!((c.nc >= 'a' && c.nc <= 'z') ||
- (c.nc >= 'A' && c.nc <= 'Z') ||
- (c.nc >= '0' && c.nc <= '9') ||
- c.nc == '_')) {
- break;
- }
- tappend(c);
- }
-}
-
-feed_escape(c: *lexer) {
- var hex: int;
- var ok: int;
-
- // backslash
- feedc(c);
-
- if (c.nc == 't') {
- c.nc = '\t';
- } else if (c.nc == 'r') {
- c.nc = '\r';
- } else if (c.nc == 'n') {
- c.nc = '\n';
- } else if (c.nc == 'x') {
- c.nc = fgetc(c.in);
- hex = hexdig(c.nc, &ok) * 16;
- if !ok {
- ldie(c, "invalid escape");
- }
-
- c.nc = fgetc(c.in);
- hex = hex + hexdig(c.nc, &ok);
- if !ok {
- ldie(c, "invalid escape");
- }
-
- c.nc = hex;
- } else if (c.nc != '\\' && c.nc != '\'' && c.nc != '"') {
- ldie(c, "invalid escape");
- }
-}
-
-feed_str(c: *lexer) {
- c.tt = T_STR;
-
- // quote
- feedc(c);
-
- loop {
- if (c.nc == '"') {
- feedc(c);
- return;
- }
-
- if (c.nc == -1 || c.nc == 0 || c.nc == '\n') {
- ldie(c, "invalid char in string");
- }
-
- if (c.tlen == c.tmax) {
- ldie(c, "string too long");
- }
-
- if (c.nc == '\\') {
- feed_escape(c);
- }
-
- tappend(c);
- }
-}
-
-feed_char(c: *lexer) {
- c.tt = T_CHAR;
-
- // quote
- feedc(c);
-
- if (c.nc == 0 || c.nc == -1 || c.nc == '\'' || c.nc == '\n') {
- ldie(c, "invalid char");
- }
-
- if (c.nc == '\\') {
- feed_escape(c);
- }
-
- tappend(c);
-
- if (c.nc != '\'') {
- ldie(c, "expected '");
- }
-
- feedc(c);
-}
-
-feed_hex(c: *lexer) {
- c.tt = T_HEX;
-
- loop {
- if (!((c.nc >= '0' && c.nc <= '9')
- || (c.nc >= 'a' && c.nc <= 'f')
- || (c.nc >= 'A' && c.nc <= 'F'))) {
- break;
- }
-
- tappend(c);
- }
-
- if (c.tlen == 0) {
- ldie(c, "expected hex");
- }
-}
-
-feed_num(c: *lexer) {
- c.tt = T_NUM;
-
- if (c.nc == '0') {
- tappend(c);
-
- if (c.nc == 'x') {
- feedc(c);
- feed_hex(c);
- return;
- }
- }
-
- loop {
- if (!(c.nc >= '0' && c.nc <= '9')) {
- break;
- }
-
- tappend(c);
- }
-}
diff --git a/attic/parse1.om b/attic/parse1.om
@@ -1,1446 +0,0 @@
-struct parser {
- a: *alloc;
- l: *lexer;
-}
-
-pdie(c: *parser, msg: *byte) {
- ldie(c.l, msg);
-}
-
-setup_parser(a: *alloc): *parser {
- var c: *parser;
-
- c = alloc(a, sizeof(*c)):*parser;
-
- c.a = a;
-
- c.l = setup_lexer(a);
-
- return c;
-}
-
-// Copy the current token
-intern(c: *parser): *byte {
- var ret: *byte;
- var i: int;
-
- ret = alloc(c.a, c.l.tlen + 1);
-
- i = 0;
- loop {
- if (i == c.l.tlen) {
- ret[i] = 0:byte;
- return ret;
- }
-
- ret[i] = c.l.token[i];
-
- i = i + 1;
- }
-}
-
-// ident := IDENT
-parse_ident(c: *parser): *node {
- var n: *node;
-
- if (c.l.tt != T_IDENT) {
- return 0:*node;
- }
-
- n = mknode0(c, N_IDENT);
- n.s = intern(c);
- feed(c.l);
-
- return n;
-}
-
-parse_hex(c: *parser): *node {
- var n: *node;
- var x: int;
- var d: int;
- var i: int;
-
- x = 0;
- i = 0;
- loop {
- if (i == c.l.tlen) {
- break;
- }
-
- d = c.l.token[i]:int;
-
- if (d >= '0' && d <= '9') {
- d = d - '0';
- } else if (d >= 'a' && d <= 'f') {
- d = (d - 'a') + 10;
- } else {
- d = (d - 'A') + 10;
- }
-
- x = x * 16;
- x = x + d;
- i = i + 1;
-
- if (x > 0x7fffffff) {
- pdie(c, "overflow");
- }
- }
-
- n = mknode0(c, N_NUM);
- n.n = x;
- feed(c.l);
-
- return n;
-}
-
-// num := NUM
-parse_num(c: *parser): *node {
- var n: *node;
- var x: int;
- var d: int;
- var i: int;
-
- if (c.l.tt == T_HEX) {
- return parse_hex(c);
- }
-
- if (c.l.tt != T_NUM) {
- return 0:*node;
- }
-
- x = 0;
- i = 0;
- loop {
- if (i == c.l.tlen) {
- break;
- }
-
- d = (c.l.token[i]:int) - '0';
-
- x = x * 10;
-
- x = x + d;
- i = i + 1;
-
- if (x > 0x7fffffff) {
- pdie(c, "overflow");
- }
- }
-
- n = mknode0(c, N_NUM);
- n.n = x;
- feed(c.l);
-
- return n;
-}
-
-// chr := CHAR
-parse_chr(c: *parser): *node {
- var n: *node;
-
- if (c.l.tt != T_CHAR) {
- return 0:*node;
- }
-
- n = mknode0(c, N_CHAR);
- n.n = c.l.token[0]:int;
- feed(c.l);
-
- return n;
-}
-
-// str := STR
-parse_str(c: *parser): *node {
- var n: *node;
-
- if (c.l.tt != T_STR) {
- return 0:*node;
- }
-
- n = mknode0(c, N_STR);
- n.s = intern(c);
- feed(c.l);
-
- return n;
-}
-
-// primary := ident
-// | num
-// | str
-// | chr
-// | '(' expr ')'
-parse_primary(c: *parser): *node {
- var n: *node;
-
- n = parse_ident(c);
- if (n) {
- return n;
- }
-
- n = parse_num(c);
- if (n) {
- return n;
- }
-
- n = parse_str(c);
- if (n) {
- return n;
- }
-
- n = parse_chr(c);
- if (n) {
- return n;
- }
-
- if (c.l.tt == T_LPAR) {
- feed(c.l);
-
- n = parse_expr(c);
- if (!n) {
- pdie(c, "expected expr");
- }
-
- if (c.l.tt != T_RPAR) {
- pdie(c, "expected )");
- }
- feed(c.l);
-
- return n;
- }
-
- return 0:*node;
-}
-
-// expr_list := expr
-// | expr ',' expr_list
-parse_expr_list(c: *parser): *node {
- var n: *node;
- var e: *node;
- var a: *node;
-
- a = parse_expr(c);
- if (!a) {
- return 0:*node;
- }
-
- e = mknode1(c, N_EXPRLIST, a);
- n = e;
-
- loop {
- if (c.l.tt != T_COMMA) {
- return n;
- }
- feed(c.l);
-
- a = parse_expr(c);
- if (!a) {
- pdie(c, "expected expr");
- }
-
- e.b = mknode1(c, N_EXPRLIST, a);
- e = e.b;
- }
-}
-
-// post_expr := primary
-// | 'sizeof' '(' expr ')'
-// | post_expr '[' expr ']'
-// | post_expr '(' expr_list ')'
-// | post_expr '.' ident
-// | post_expr ':' type
-parse_post_expr(c: *parser): *node {
- var n: *node;
- var b: *node;
-
- if (c.l.tt == T_IDENT && !strcmp(c.l.token, "sizeof")) {
- feed(c.l);
-
- if (c.l.tt != T_LPAR) {
- pdie(c, "expected (");
- }
- feed(c.l);
-
- n = parse_expr(c);
- if (!n) {
- pdie(c, "expected expr");
- }
-
- if (c.l.tt != T_RPAR) {
- pdie(c, "expected )");
- }
- feed(c.l);
-
- return mknode1(c, N_SIZEOF, n);
- }
-
- n = parse_primary(c);
- if (!n) {
- return 0:*node;
- }
-
- loop {
- if (c.l.tt == T_LSQ) {
- feed(c.l);
-
- b = parse_expr(c);
-
- if (c.l.tt != T_RSQ) {
- pdie(c, "expected ]");
- }
- feed(c.l);
-
- n = mknode(c, N_INDEX, n, b);
- } else if (c.l.tt == T_LPAR) {
- feed(c.l);
-
- b = parse_expr_list(c);
-
- if (c.l.tt != T_RPAR) {
- pdie(c, "expected )");
- }
- feed(c.l);
-
- n = mknode(c, N_CALL, n, b);
- } else if (c.l.tt == T_DOT) {
- feed(c.l);
-
- b = parse_ident(c);
- if (!b) {
- pdie(c, "expected ident");
- }
-
- n = mknode(c, N_DOT, n, b);
- } else if (c.l.tt == T_COLON) {
- feed(c.l);
-
- b = parse_type(c);
- if (!b) {
- pdie(c, "expected type");
- }
-
- n = mknode(c, N_CAST, n, b);
- } else {
- return n;
- }
- }
-}
-
-// unary_expr := post_expr
-// | '&' unary_expr
-// | '*' unary_expr
-// | '+' unary_expr
-// | '-' unary_expr
-// | '~' unary_expr
-// | '!' unary_expr
-parse_unary_expr(c: *parser): *node {
- var n: *node;
-
- if (c.l.tt == T_AMP) {
- feed(c.l);
-
- n = parse_unary_expr(c);
- if (!n) {
- pdie(c, "expected unary_expr");
- }
-
- return mknode1(c, N_REF, n);
- }
-
- if (c.l.tt == T_STAR) {
- feed(c.l);
-
- n = parse_unary_expr(c);
- if (!n) {
- pdie(c, "expected unary_expr");
- }
-
- return mknode1(c, N_DEREF, n);
- }
-
- if (c.l.tt == T_ADD) {
- feed(c.l);
-
- n = parse_unary_expr(c);
- if (!n) {
- pdie(c, "expected unary_expr");
- }
-
- return mknode1(c, N_POS, n);
- }
-
- if (c.l.tt == T_SUB) {
- feed(c.l);
-
- n = parse_unary_expr(c);
- if (!n) {
- pdie(c, "expected unary_expr");
- }
-
- return mknode1(c, N_NEG, n);
- }
-
- if (c.l.tt == T_NOT) {
- feed(c.l);
-
- n = parse_unary_expr(c);
- if (!n) {
- pdie(c, "expected unary_expr");
- }
-
- return mknode1(c, N_NOT, n);
- }
-
- if (c.l.tt == T_BANG) {
- feed(c.l);
-
- n = parse_unary_expr(c);
- if (!n) {
- pdie(c, "expected unary_expr");
- }
-
- return mknode1(c, N_BNOT, n);
- }
-
- return parse_post_expr(c);
-}
-
-
-// shift_expr := unary_expr
-// | shift_expr '<<' unary_expr
-// | shift_expr '>>' unary_expr
-parse_shift_expr(c: *parser): *node {
- var a: *node;
- var b: *node;
-
- a = parse_unary_expr(c);
- if (!a) {
- return 0:*node;
- }
-
- loop {
- if (c.l.tt == T_LSH) {
- feed(c.l);
-
- b = parse_unary_expr(c);
- if (!b) {
- pdie(c, "expected unary_expr");
- }
-
- a = mknode(c, N_LSH, a, b);
- } else if (c.l.tt == T_RSH) {
- feed(c.l);
-
- b = parse_unary_expr(c);
- if (!b) {
- pdie(c, "expected unary_expr");
- }
-
- a = mknode(c, N_RSH, a, b);
- } else {
- return a;
- }
- }
-}
-
-// mul_expr := shift_expr
-// | mul_expr '*' shift_expr
-// | mul_expr '/' shift_expr
-// | mul_expr '%' shift_expr
-// | mul_expr '&' shift_expr
-parse_mul_expr(c: *parser): *node {
- var a: *node;
- var b: *node;
-
- a = parse_shift_expr(c);
- if (!a) {
- return 0:*node;
- }
-
- loop {
- if (c.l.tt == T_STAR) {
- feed(c.l);
-
- b = parse_shift_expr(c);
- if (!b) {
- pdie(c, "expected shift_expr");
- }
-
- a = mknode(c, N_MUL, a, b);
- } else if (c.l.tt == T_DIV) {
- feed(c.l);
-
- b = parse_shift_expr(c);
- if (!b) {
- pdie(c, "expected shift_expr");
- }
-
- a = mknode(c, N_DIV, a, b);
- } else if (c.l.tt == T_MOD) {
- feed(c.l);
-
- b = parse_shift_expr(c);
- if (!b) {
- pdie(c, "expected shift_expr");
- }
-
- a = mknode(c, N_MOD, a, b);
- } else if (c.l.tt == T_AMP) {
- feed(c.l);
-
- b = parse_shift_expr(c);
- if (!b) {
- pdie(c, "expected shift_expr");
- }
-
- a = mknode(c, N_AND, a, b);
- } else {
- return a;
- }
- }
-}
-
-// add_expr := mul_expr
-// | add_expr '+' mul_expr
-// | add_expr '-' mul_expr
-// | add_expr '|' mul_expr
-// | add_expr '^' mul_expr
-parse_add_expr(c: *parser): *node {
- var a: *node;
- var b: *node;
-
- a = parse_mul_expr(c);
- if (!a) {
- return 0:*node;
- }
-
- loop {
- if (c.l.tt == T_ADD) {
- feed(c.l);
-
- b = parse_mul_expr(c);
- if (!b) {
- pdie(c, "expected mul_expr");
- }
-
- a = mknode(c, N_ADD, a, b);
- } else if (c.l.tt == T_SUB) {
- feed(c.l);
-
- b = parse_mul_expr(c);
- if (!b) {
- pdie(c, "expected mul_expr");
- }
-
- a = mknode(c, N_SUB, a, b);
- } else if (c.l.tt == T_OR) {
- feed(c.l);
-
- b = parse_mul_expr(c);
- if (!b) {
- pdie(c, "expected mul_expr");
- }
-
- a = mknode(c, N_OR, a, b);
- } else if (c.l.tt == T_XOR) {
- feed(c.l);
-
- b = parse_mul_expr(c);
- if (!b) {
- pdie(c, "expected mul_expr");
- }
-
- a = mknode(c, N_XOR, a, b);
- } else {
- return a;
- }
- }
-}
-
-// comp_expr := add_expr
-// | add_expr '<' add_expr
-// | add_expr '>' add_expr
-// | add_expr '<=' add_expr
-// | add_expr '>=' add_expr
-// | add_expr '==' add_expr
-// | add_expr '!=' add_expr
-parse_comp_expr(c: *parser): *node {
- var a: *node;
- var b: *node;
-
- a = parse_add_expr(c);
- if (!a) {
- return 0:*node;
- }
-
- if (c.l.tt == T_LT) {
- feed(c.l);
-
- b = parse_add_expr(c);
- if (!b) {
- pdie(c, "expected add_expr");
- }
-
- return mknode(c, N_LT, a, b);
- }
-
- if (c.l.tt == T_GT) {
- feed(c.l);
-
- b = parse_add_expr(c);
- if (!b) {
- pdie(c, "expected add_expr");
- }
-
- return mknode(c, N_GT, a, b);
- }
-
- if (c.l.tt == T_LE) {
- feed(c.l);
-
- b = parse_add_expr(c);
- if (!b) {
- pdie(c, "expected add_expr");
- }
-
- return mknode(c, N_LE, a, b);
- }
-
- if (c.l.tt == T_GE) {
- feed(c.l);
-
- b = parse_add_expr(c);
- if (!b) {
- pdie(c, "expected add_expr");
- }
-
- return mknode(c, N_GE, a, b);
- }
-
- if (c.l.tt == T_EQ) {
- feed(c.l);
-
- b = parse_add_expr(c);
- if (!b) {
- pdie(c, "expected add_expr");
- }
-
- return mknode(c, N_EQ, a, b);
- }
-
- if (c.l.tt == T_NE) {
- feed(c.l);
-
- b = parse_add_expr(c);
- if (!b) {
- pdie(c, "expected add_expr");
- }
-
- return mknode(c, N_NE, a, b);
- }
-
- return a;
-}
-
-// bool_expr := bool_expr
-// | bool_expr '&&' comp_expr
-// | bool_expr '||' comp_expr
-parse_bool_expr(c: *parser): *node {
- var a: *node;
- var b: *node;
-
- a = parse_comp_expr(c);
- if (!a) {
- return 0:*node;
- }
-
- if (c.l.tt == T_BAND) {
- feed(c.l);
-
- b = parse_bool_expr(c);
- if (!b) {
- pdie(c, "expected bool_expr");
- }
-
- return mknode(c, N_BAND, a, b);
- }
-
- if (c.l.tt == T_BOR) {
- feed(c.l);
-
- b = parse_bool_expr(c);
- if (!b) {
- pdie(c, "expected bool_expr");
- }
-
- return mknode(c, N_BOR, a, b);
- }
-
- return a;
-}
-
-// expr := bool_expr
-// | bool_expr '=' expr
-parse_expr(c: *parser): *node {
- var a: *node;
- var b: *node;
-
- a = parse_bool_expr(c);
- if (!a) {
- return 0:*node;
- }
-
- if (c.l.tt == T_ASSIGN) {
- feed(c.l);
-
- b = parse_expr(c);
- if (!b) {
- pdie(c, "expected expr");
- }
-
- return mknode(c, N_ASSIGN, a, b);
- }
-
- return a;
-}
-
-// if_stmt := 'if' expr '{' stmt_list '}'
-// | 'if' expr '{' stmt_list '}' 'else' if_stmt
-// | 'if' expr '{' stmt_list '}' 'else' '{' stmt_list '}'
-parse_if_stmt(c: *parser): *node {
- var n: *node;
- var e: *node;
- var a: *node;
- var b: *node;
-
- if (c.l.tt != T_IDENT || strcmp(c.l.token, "if")) {
- return 0:*node;
- }
- feed(c.l);
-
- n = mknode0(c, N_CONDLIST);
- e = n;
-
- loop {
- a = parse_expr(c);
- if !a {
- pdie(c, "expected expr");
- }
-
- if (c.l.tt != T_LBRA) {
- pdie(c, "expected {");
- }
- feed(c.l);
-
- b = parse_stmt_list(c);
-
- if (c.l.tt != T_RBRA) {
- pdie(c, "expected }");
- }
- feed(c.l);
-
- e.a = mknode(c, N_COND, a, b);
-
- if (c.l.tt != T_IDENT || strcmp(c.l.token, "else")) {
- return n;
- }
- feed(c.l);
-
- if (c.l.tt == T_LBRA) {
- feed(c.l);
-
- b = parse_stmt_list(c);
-
- if (c.l.tt != T_RBRA) {
- pdie(c, "expected }");
- }
- feed(c.l);
-
- e.b = mknode1(c, N_CONDLIST, mknode(c, N_COND, 0:*node, b));
-
- return n;
- }
-
- if (c.l.tt != T_IDENT || strcmp(c.l.token, "if")) {
- pdie(c, "expected if");
- }
- feed(c.l);
-
- e.b = mknode0(c, N_CONDLIST);
- e = e.b;
- }
-}
-
-// loop_stmt := 'loop' '{' stmt_list '}'
-parse_loop_stmt(c: *parser): *node {
- var a: *node;
-
- if (c.l.tt != T_IDENT || strcmp(c.l.token, "loop")) {
- return 0:*node;
- }
- feed(c.l);
-
- if (c.l.tt != T_LBRA) {
- pdie(c, "expected {");
- }
- feed(c.l);
-
- a = parse_stmt_list(c);
-
- if (c.l.tt != T_RBRA) {
- pdie(c, "expected }");
- }
- feed(c.l);
-
- return mknode1(c, N_LOOP, a);
-}
-
-// break_stmt := 'break'
-parse_break_stmt(c: *parser): *node {
- if (c.l.tt != T_IDENT || strcmp(c.l.token, "break")) {
- return 0:*node;
- }
- feed(c.l);
-
- return mknode0(c, N_BREAK);
-}
-
-// continue_stmt := 'continue'
-parse_continue_stmt(c: *parser): *node {
- if (c.l.tt != T_IDENT || strcmp(c.l.token, "continue")) {
- return 0:*node;
- }
- feed(c.l);
-
- return mknode0(c, N_CONTINUE);
-}
-
-// return_stmt := 'return'
-// | 'return' expr
-parse_return_stmt(c: *parser): *node {
- var a: *node;
-
- if (c.l.tt != T_IDENT || strcmp(c.l.token, "return")) {
- return 0:*node;
- }
- feed(c.l);
-
- a = parse_expr(c);
-
- return mknode1(c, N_RETURN, a);
-}
-
-// var_decl := ident ':' type
-parse_var_decl(c: *parser): *node {
- var n: *node;
- var a: *node;
- var b: *node;
-
- a = parse_ident(c);
- if (!a) {
- return 0:*node;
- }
-
- if (c.l.tt != T_COLON) {
- pdie(c, "expected :");
- }
- feed(c.l);
-
- b = parse_type(c);
- if (!b) {
- pdie(c, "expected type");
- }
-
- return mknode(c, N_VARDECL, a, b);
-}
-
-// var_stmt := 'var' var_decl
-parse_var_stmt(c: *parser): *node {
- var a: *node;
-
- if (c.l.tt != T_IDENT || strcmp(c.l.token, "var")) {
- return 0:*node;
- }
- feed(c.l);
-
- a = parse_var_decl(c);
- if (!a) {
- pdie(c, "expected var_decl");
- }
-
- return a;
-}
-
-// label_stmt := ':' ident
-parse_label_stmt(c: *parser): *node {
- var a: *node;
-
- if (c.l.tt != T_COLON) {
- return 0:*node;
- }
- feed(c.l);
-
- a = parse_ident(c);
- if (!a) {
- pdie(c, "expected ident");
- }
-
- return mknode1(c, N_LABEL, a);
-}
-
-// goto_stmt := 'goto' ident
-parse_goto_stmt(c: *parser): *node {
- var a: *node;
-
- if (c.l.tt != T_IDENT || strcmp(c.l.token, "goto")) {
- return 0:*node;
- }
- feed(c.l);
-
- a = parse_ident(c);
- if (!a) {
- pdie(c, "expected ident");
- }
-
- return mknode1(c, N_GOTO, a);
-}
-
-// stmt := if_stmt
-// | loop_stmt
-// | break_stmt ';'
-// | continue_stmt ';'
-// | return_stmt ';'
-// | var_stmt ';'
-// | label_stmt ';'
-// | goto_stmt ';'
-// | expr ';'
-parse_stmt(c: *parser): *node {
- var n: *node;
-
- n = parse_if_stmt(c);
- if (n) {
- return n;
- }
-
- n = parse_loop_stmt(c);
- if (n) {
- return n;
- }
-
- n = parse_break_stmt(c);
- if (n) {
- if (c.l.tt != T_SEMI) {
- pdie(c, "expected ;");
- }
- feed(c.l);
-
- return n;
- }
-
- n = parse_return_stmt(c);
- if (n) {
- if (c.l.tt != T_SEMI) {
- pdie(c, "expected ;");
- }
- feed(c.l);
-
- return n;
- }
-
- n = parse_continue_stmt(c);
- if (n) {
- if (c.l.tt != T_SEMI) {
- pdie(c, "expected ;");
- }
- feed(c.l);
-
- return n;
- }
-
- n = parse_var_stmt(c);
- if (n) {
- if (c.l.tt != T_SEMI) {
- pdie(c, "expected ;");
- }
- feed(c.l);
-
- return n;
- }
-
- n = parse_label_stmt(c);
- if (n) {
- if (c.l.tt != T_SEMI) {
- pdie(c, "expected ;");
- }
- feed(c.l);
-
- return n;
- }
-
- n = parse_goto_stmt(c);
- if (n) {
- if (c.l.tt != T_SEMI) {
- pdie(c, "expected ;");
- }
- feed(c.l);
-
- return n;
- }
-
- n = parse_expr(c);
- if (n) {
- if (c.l.tt != T_SEMI) {
- pdie(c, "expected ;");
- }
- feed(c.l);
-
- return n;
- }
-
- return 0:*node;
-}
-
-// stmt_list := stmt
-// | stmt stmt_list
-parse_stmt_list(c: *parser): *node {
- var n: *node;
- var e: *node;
- var a: *node;
-
- a = parse_stmt(c);
- if (!a) {
- return 0:*node;
- }
-
- e = mknode1(c, N_STMTLIST, a);
- n = e;
-
- loop {
- a = parse_stmt(c);
- if (!a) {
- return n;
- }
-
- e.b = mknode1(c, N_STMTLIST, a);
- e = e.b;
- }
-}
-
-// enum_item := ident
-// | ident '=' num
-parse_enum_item(c: *parser): *node {
- var a: *node;
- var b: *node;
-
- a = parse_ident(c);
- if (!a) {
- return 0:*node;
- }
-
- if (c.l.tt != T_ASSIGN) {
- return mknode1(c, N_ENUMITEM, a);
- }
- feed(c.l);
-
- b = parse_num(c);
- if (!b) {
- pdie(c, "expected num");
- }
-
- return mknode(c, N_ENUMITEM, a, b);
-}
-
-// enum_list := enum_item
-// | enum_list ',' enum_list
-parse_enum_list(c: *parser): *node {
- var n: *node;
- var e: *node;
- var a: *node;
-
- a = parse_enum_item(c);
- if (!a) {
- return 0:*node;
- }
-
- e = mknode1(c, N_ENUMLIST, a);
- n = e;
-
- loop {
- if (c.l.tt != T_COMMA) {
- return n;
- }
- feed(c.l);
-
- a = parse_enum_item(c);
- if (!a) {
- return n;
- }
-
- e.b = mknode1(c, N_ENUMLIST, a);
- e = e.b;
- }
-}
-
-// enum_decl := 'enum' ident '{' enum_list '}'
-parse_enum_decl(c: *parser): *node {
- var b: *node;
-
- if (c.l.tt != T_IDENT) {
- return 0:*node;
- }
-
- if (strcmp(c.l.token, "enum")) {
- return 0:*node;
- }
- feed(c.l);
-
- if (c.l.tt != T_LBRA) {
- pdie(c, "expected {");
- }
- feed(c.l);
-
- b = parse_enum_list(c);
-
- if (c.l.tt != T_RBRA) {
- pdie(c, "expected }");
- }
- feed(c.l);
-
- return mknode(c, N_ENUM, 0:*node, b);
-}
-
-// type := ident
-// | '*' type
-// | '(' type ')'
-// | 'func' func_type
-parse_type(c: *parser): *node {
- var n: *node;
-
- if (c.l.tt == T_STAR) {
- feed(c.l);
-
- n = parse_type(c);
-
- return mknode1(c, N_PTRTYPE, n);
- }
-
- if (c.l.tt == T_LPAR) {
- feed(c.l);
-
- n = parse_type(c);
-
- if (c.l.tt != T_RPAR) {
- pdie(c, "expected )");
- }
- feed(c.l);
-
- return n;
- }
-
- if (c.l.tt == T_IDENT && !strcmp(c.l.token, "func")) {
- feed(c.l);
-
- n = parse_func_type(c);
- if (!n) {
- pdie(c, "expected func_type");
- }
-
- return n;
- }
-
- return parse_ident(c);
-}
-
-// member_decl := ident ':' type
-parse_member_decl(c: *parser): *node {
- var n: *node;
- var a: *node;
- var b: *node;
-
- a = parse_ident(c);
- if (!a) {
- return 0: *node;
- }
-
- if (c.l.tt != T_COLON) {
- pdie(c, "expected :");
- }
- feed(c.l);
-
- b = parse_type(c);
- if (!b) {
- pdie(c, "expected type");
- }
-
- return mknode(c, N_MEMBERDECL, a, b);
-}
-
-// member_list := member_decl
-// | member_decl ';' member_list
-parse_member_list(c: *parser): *node {
- var n: *node;
- var e: *node;
- var a: *node;
-
- a = parse_member_decl(c);
- if (!a) {
- return 0:*node;
- }
-
- e = mknode1(c, N_MEMBERLIST, a);
- n = e;
-
- loop {
- if (c.l.tt != T_SEMI) {
- return n;
- }
- feed(c.l);
-
- a = parse_member_decl(c);
- if (!a) {
- return n;
- }
-
- e.b = mknode1(c, N_MEMBERLIST, a);
- e = e.b;
- }
-}
-
-// struct_decl := 'struct' ident '{' member_list '}'
-parse_struct_decl(c: *parser): *node {
- var a: *node;
- var b: *node;
-
- if (c.l.tt != T_IDENT) {
- return 0:*node;
- }
-
- if (strcmp(c.l.token, "struct")) {
- return 0:*node;
- }
- feed(c.l);
-
- a = parse_ident(c);
- if (!a) {
- pdie(c, "expected ident");
- }
-
- if (c.l.tt != T_LBRA) {
- pdie(c, "expected {");
- }
- feed(c.l);
-
- b = parse_member_list(c);
-
- if (c.l.tt != T_RBRA) {
- pdie(c, "expected }");
- }
- feed(c.l);
-
- return mknode(c, N_STRUCT, a, b);
-}
-
-// arg_decl := ':' type
-// ident ':' type
-parse_arg_decl(c: *parser): *node {
- var n: *node;
- var a: *node;
- var b: *node;
-
- a = parse_ident(c);
- if (!a) {
- return 0:*node;
- }
-
- if (c.l.tt != T_COLON) {
- pdie(c, "expected :");
- }
- feed(c.l);
-
- b = parse_type(c);
- if (!b) {
- pdie(c, "expected type");
- }
-
- return mknode(c, N_ARGDECL, a, b);
-}
-
-// arg_list := arg_decl
-// | arg_decl ',' arg_list
-parse_arg_list(c: *parser): *node {
- var n: *node;
- var e: *node;
- var a: *node;
-
- a = parse_arg_decl(c);
- if (!a) {
- return 0:*node;
- }
-
- e = mknode1(c, N_ARGLIST, a);
- n = e;
-
- loop {
- if (c.l.tt != T_COMMA) {
- return n;
- }
- feed(c.l);
-
- a = parse_arg_decl(c);
- if (!a) {
- pdie(c, "expected identifier");
- }
-
- e.b = mknode1(c, N_ARGLIST, a);
- e = e.b;
- }
-}
-
-// func_type := '(' ')' ':' type
-// | '(' arg_list ')' ':' type
-// | '(' ')'
-// | '(' arg_list ')'
-parse_func_type(c: *parser): *node {
- var a: *node;
- var b: *node;
-
- if (c.l.tt != T_LPAR) {
- return 0: *node;
- }
- feed(c.l);
-
- a = parse_arg_list(c);
-
- if (c.l.tt != T_RPAR) {
- pdie(c, "expected )");
- }
- feed(c.l);
-
- if (c.l.tt != T_COLON) {
- return mknode1(c, N_FUNCTYPE, a);
- }
- feed(c.l);
-
- b = parse_type(c);
- if (!b) {
- pdie(c, "expected type");
- }
-
- return mknode(c, N_FUNCTYPE, a, b);
-}
-
-// func_decl := ident func_type
-parse_func_decl(c: *parser): *node {
- var a: *node;
- var b: *node;
-
- a = parse_ident(c);
- if (!a) {
- return 0:*node;
- }
-
- b = parse_func_type(c);
- if (!b) {
- pdie(c, "expected func_type");
- }
-
- return mknode(c, N_FUNCDECL, a, b);
-}
-
-// func := func_decl '{' stmt_list '}'
-// | func_decl ';'
-parse_func(c: *parser): *node {
- var n: *node;
- var a: *node;
- var b: *node;
-
- a = parse_func_decl(c);
- if (!a) {
- return 0:*node;
- }
-
- if (c.l.tt == T_SEMI) {
- feed(c.l);
- return a;
- }
-
- if (c.l.tt != T_LBRA) {
- pdie(c, "expected {");
- }
- feed(c.l);
-
- b = parse_stmt_list(c);
-
- if (c.l.tt != T_RBRA) {
- pdie(c, "expected }");
- }
- feed(c.l);
-
- return mknode(c, N_FUNC, a, b);
-}
-
-// decl := enum_decl
-// | struct_decl
-// | func
-parse_decl(c: *parser): *node {
- var n: *node;
-
- n = parse_enum_decl(c);
- if (n) {
- return n;
- }
-
- n = parse_struct_decl(c);
- if (n) {
- return n;
- }
-
- return parse_func(c);
-}
-
-// program := decl
-// | decl program
-parse_program(c: *parser): *node {
- var n: *node;
- var e: *node;
- var d: *node;
-
- d = parse_decl(c);
- if (!d) {
- if (c.l.tt != T_EOF) {
- pdie(c, "expected eof");
- }
- return 0:*node;
- }
-
- e = mknode1(c, N_PROGRAM, d);
- n = e;
-
- loop {
- d = parse_decl(c);
- if (!d) {
- if (c.l.tt != T_EOF) {
- pdie(c, "expected eof");
- }
-
- e.b = 0:*node;
- return n;
- }
-
- e.b = mknode1(c, N_PROGRAM, d);
- e = e.b;
- }
-}
-
-parse(c: *parser, filename: *byte): *node {
- var p: *node;
- open_source(c.l, filename);
- p = parse_program(c);
- close_source(c.l);
- return p;
-}
-
-fillpos(c: *parser, n: *node) {
- n.filename = c.l.filename;
- n.lineno = c.l.lineno;
- n.colno = c.l.colno;
-}
diff --git a/attic/poly1305_test.om b/attic/poly1305_test.om
@@ -1,55 +0,0 @@
-main(c: int, v: **byte, e: **byte) {
- var _key: _poly1305_ctx;
- var _text: _poly1305_ctx;
- var _mac: _poly1305_ctx;
- var key: *byte;
- var text: *byte;
- var mac: *byte;
-
- key = (&_key):*byte;
- text = (&_text):*byte;
- mac = (&_mac):*byte;
-
- bzero(key, 32);
- bzero(text, 64);
- bzero(mac, 32);
-
- poly1305(mac, key, text, 64);
- fdxxd(1, mac, 16);
-
- key[0] = 0x85:byte;
- key[1] = 0xd6:byte;
- key[2] = 0xbe:byte;
- key[3] = 0x78:byte;
- key[4] = 0x57:byte;
- key[5] = 0x55:byte;
- key[6] = 0x6d:byte;
- key[7] = 0x33:byte;
- key[8] = 0x7f:byte;
- key[9] = 0x44:byte;
- key[10] = 0x52:byte;
- key[11] = 0xfe:byte;
- key[12] = 0x42:byte;
- key[13] = 0xd5:byte;
- key[14] = 0x06:byte;
- key[15] = 0xa8:byte;
- key[16] = 0x01:byte;
- key[17] = 0x03:byte;
- key[18] = 0x80:byte;
- key[19] = 0x8a:byte;
- key[20] = 0xfb:byte;
- key[21] = 0x0d:byte;
- key[22] = 0xb2:byte;
- key[23] = 0xfd:byte;
- key[24] = 0x4a:byte;
- key[25] = 0xbf:byte;
- key[26] = 0xf6:byte;
- key[27] = 0xaf:byte;
- key[28] = 0x41:byte;
- key[29] = 0x49:byte;
- key[30] = 0xf5:byte;
- key[31] = 0x1b:byte;
-
- poly1305(mac, key, "Cryptographic Forum Research Group", 34);
- fdxxd(1, mac, 16);
-}
diff --git a/attic/rsa.om b/attic/rsa.om
@@ -1,266 +0,0 @@
-rsa_mul(y: *int, a: *int, b: *int, n: int) {
- var c: int;
- var i: int;
- var j: int;
-
- i = 0;
- loop {
- if i == 2 * n {
- break;
- }
-
- y[i] = 0;
-
- i = i + 1;
- }
-
- i = 0;
- loop {
- if i == n {
- break;
- }
-
- j = 0;
- c = 0;
- loop {
- if j == n {
- break;
- }
-
- c = c + (a[i] & (-1 >> 32)) * (b[j] & (-1 >> 32));
- c = c + y[i + j];
- y[i + j] = c & (-1 >> 32);
-
- c = c >> 32;
- j = j + 1;
- }
-
- j = j + i;
-
- loop {
- if j == 2 * n {
- break;
- }
-
- c = c + y[j];
- y[j] = c & (-1 >> 32);
-
- j = j + 1;
- c = c >> 32;
- }
-
- i = i + 1;
- }
-}
-
-rsa_trymod(r: *int, d: *int, q: int, n: int): int {
- var i: int;
- var a: int;
- var s: int;
-
- i = 0;
- a = 0;
- s = 1;
- loop {
- if i == n {
- break;
- }
-
- a = a + (d[i] & (-1 >> 32)) * (q & (-1 >> 32));
- s = s + ((~a) & (-1 >> 32));
- s = s + (r[i] & (-1 >> 32));
-
- i = i + 1;
- a = a >> 32;
- s = s >> 32;
- }
-
- s = s + ((~a) & (-1 >> 32));
- s = s + (r[i] & (-1 >> 32));
- s = s >> 32;
-
- return ~s & ((q + (-1 >> 32)) >> 32);
-}
-
-rsa_domod(r: *int, d: *int, q: int, n: int) {
- var i: int;
- var a: int;
- var s: int;
-
- i = 0;
- a = 0;
- s = 1;
- loop {
- if i == n {
- break;
- }
-
- a = a + (d[i] & (-1 >> 32)) * (q & (-1 >> 32));
- s = s + ((~a) & (-1 >> 32));
- s = s + (r[i] & (-1 >> 32));
- r[i] = s & (-1 >> 32);
-
- i = i + 1;
- a = a >> 32;
- s = s >> 32;
- }
-
- s = s + ((~a) & (-1 >> 32));
- s = s + (r[i] & (-1 >> 32));
- r[i] = s & (-1 >> 32);
-}
-
-// Based on https://ridiculousfish.com/blog/posts/labor-of-division-episode-iv.html
-rsa_mod(r: *int, x: *int, d: *int, n: int) {
- var i: int;
- var j: int;
- var nd: int;
- var k: int;
- var h: int;
- var q: int;
- var a: int;
-
- // Find the size of d
- nd = n;
- loop {
- if (d[nd - 1] & (- 1 >> 32)) != 0 || nd == 0 {
- break;
- }
-
- nd = nd - 1;
- }
-
- // Divide by a single word
- if (nd == 1) {
- i = 2 * n - 1;
- a = 0;
- loop {
- a = ((a << 32) + (x[i] & (- 1 >> 32))) % (d[nd - 1] & (- 1 >> 32));
- r[i] = 0;
-
- if i == 0 {
- break;
- }
-
- i = i - 1;
- }
-
- r[0] = a;
- return;
- }
-
- // Find the fudge factor
- h = d[nd - 1];
- k = 0;
- loop {
- if h & (1 << 31) != 0 {
- break;
- }
-
- h = h << 1;
-
- k = k + 1;
- }
- h = h | ((d[nd - 2] & (- 1 >> 32)) << k) >> 32;
-
- // Copy x to r
- i = 0;
- loop {
- if i == 2 * n {
- break;
- }
-
- r[i] = x[i] & (- 1 >> 32);
-
- i = i + 1;
- }
- r[i] = 0;
-
- i = 2 * n;
- j = 2 * n - nd;
- loop {
- a = (r[i] << (k + 32))
- | (r[i - 1] << k)
- | ((r[i - 2] << k) >> 32);
-
- // Compute guess
- q = a / h;
-
- // Bump it down
- q = q - (q >> 32);
-
- // Try twice since it is at most +2 from the lower guess
- q = q - rsa_trymod(&r[j], d, q, n);
- q = q - rsa_trymod(&r[j], d, q, n);
-
- rsa_domod(&r[j], d, q, n);
-
- if j == 0 {
- break;
- }
-
- i = i - 1;
- j = j - 1;
- }
-}
-
-rsa_sel(y: *int, x: *int, n: int, s: int) {
- var i: int;
-
- loop {
- if i == n {
- break;
- }
-
- y[i] = ((y[i] & ~s) | (x[i] & s)) & (-1 >> 32);
-
- i = i + 1;
- }
-}
-
-rsa_pow(y: *int, x: *int, d: *int, m: *int, t: *int, n: int) {
- var nd: int;
- var i: int;
- var e: int;
-
- y[0] = 1;
-
- i = 1;
- loop {
- if i == 2 * n {
- break;
- }
-
- y[i] = 0;
-
- i = i + 1;
- }
-
- nd = n - 1;
- loop {
- i = 0;
- e = d[nd];
- loop {
- if i == 32 {
- break;
- }
-
- rsa_mul(t, y, y, n);
- rsa_mod(y, t, m, n);
-
- rsa_mul(t, y, x, n);
- rsa_mod(t, t, m, n);
-
- rsa_sel(y, t, n, -((e >> 31) & 1));
-
- i = i + 1;
- e = e << 1;
- }
-
- if nd == 0 {
- break;
- }
-
- nd = nd - 1;
- }
-}
diff --git a/attic/sha256_test.om b/attic/sha256_test.om
@@ -1,14 +0,0 @@
-main(argc: int, argv: **byte, envp: **byte) {
- var d: _sha256_digest;
- var digest: *byte;
- digest = (&d):*byte;
- if argc == 2 {
- sha256(digest, argv[1], strlen(argv[1]));
- fdxxd(1, digest, 32);
- } else if argc == 3 {
- sha256_hmac(digest, argv[1], strlen(argv[1]), argv[2], strlen(argv[2]));
- fdxxd(1, digest, 32);
- } else {
- exit(2);
- }
-}
diff --git a/attic/sha512_test.om b/attic/sha512_test.om
@@ -1,14 +0,0 @@
-main(argc: int, argv: **byte, envp: **byte) {
- var d: _sha512_digest;
- var digest: *byte;
- digest = (&d):*byte;
- if argc == 2 {
- sha512(digest, argv[1], strlen(argv[1]));
- fdxxd(1, digest, 64);
- } else if argc == 3 {
- sha512_hmac(digest, argv[1], strlen(argv[1]), argv[2], strlen(argv[2]));
- fdxxd(1, digest, 64);
- } else {
- exit(2);
- }
-}
diff --git a/attic/x25519_test.om b/attic/x25519_test.om
@@ -1,38 +0,0 @@
-main(argc: int, argv: **byte, envp: **byte) {
- var _a: _ed25519_point;
- var a: *byte;
- var _b: _ed25519_point;
- var b: *byte;
- var _c: _ed25519_point;
- var c: *byte;
-
- a = (&_a):*byte;
- b = (&_b):*byte;
- c = (&_c):*byte;
-
- assert(unhex(a, "e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c") == 32, "unhex");
- assert(unhex(b, "a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4") == 32, "unhex");
- assert(x25519(c, a, b), "decode");
- fdxxd(1, c, 32);
- fdputc(1, '\n');
-
- x25519_base(a);
- assert(unhex(b, "77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a") == 32, "unhex");
- assert(x25519(c, a, b), "decode");
- fdxxd(1, c, 32);
- fdputc(1, '\n');
-
- x25519_base(a);
- assert(unhex(b, "5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb") == 32, "unhex");
- assert(x25519(c, a, b), "decode");
- fdxxd(1, c, 32);
- fdputc(1, '\n');
-
- x25519_base(a);
- assert(unhex(b, "5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb") == 32, "unhex");
- assert(x25519(c, a, b), "decode");
- assert(unhex(b, "77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a") == 32, "unhex");
- assert(x25519(c, c, b), "decode");
- fdxxd(1, c, 32);
- fdputc(1, '\n');
-}
diff --git a/build.sh b/build.sh
@@ -1,7 +1,7 @@
#!/bin/sh
LIBS="peglib.om bufio.om lib.om alloc.om syscall.om"
-CRYPTO="ed25519.om sha512.om sha256.om chacha20.om poly1305.om"
+CRYPTO="ed25519.om sha512.om sha256.om chacha20.om poly1305.om aes.om rsa.om"
CC="cc1.om type.om as.om decl.om node.om"
SSHD="chacha20.om poly1305.om sha256.om sha512.om ed25519.om sshd.om"
KERNEL="kernel.om"
@@ -20,7 +20,6 @@ ALL="${LIBS} ${CC} ${SSHD} ${KERNEL} ${SHELL} ${BIN}"
./cc1 ${LIBS} cpio.om -o cpio -n cpio.lines -G cpio.call
./cc1 ${LIBS} sh.om -o sh -n sh.lines -G sh.call
./cc1 ${LIBS} ${CRYPTO} sshd.om -o sshd -n sshd.lines -G sshd.call
-./cc1 ${LIBS} ${CRYPTO} sshd.om -o sshd -n sshd.lines -G sshd.call
for name in ${ALL}; do echo ${name}; done | ./cpio -o > initramfs
diff --git a/cc0.c b/cc0.c
@@ -28391,7 +28391,6 @@ u zpeg_P_index_expr(u vc) {
u v4 = 0;
u v5 = 0;
u v6 = 0;
- u v7 = 0;
zenter(vc, 58UL);
v1 = zliteral(vc, (u)"[");
if (v1 == 0UL) goto b1;
@@ -28408,14 +28407,8 @@ b5: v3 = zpeg_P_sp(vc);
if (v4 == 0UL) goto b1;
v5 = zliteral(vc, (u)"]");
if (v5 == 0UL) goto b1;
- zchoice(vc);
- v6 = zliteral(vc, (u)"]");
- if (v6 == 0UL) goto b17;
- zfail(vc);
- zfail(vc);
- goto b1;
-b17: v7 = zpeg_P_sp(vc);
- if (v7 == 0UL) goto b1;
+ v6 = zpeg_P_sp(vc);
+ if (v6 == 0UL) goto b1;
zleave(vc, 58UL);
return 1UL;
}
diff --git a/cc3.om b/cc3.om
@@ -88,7 +88,7 @@ peg_grammar {
bnot_op = "!" !"=";
unary_expr = ((ref_op / deref_op / pos_op / neg_op / not_op / bnot_op) sp)* post_expr;
- index_expr = "[" !"[" sp expr "]" !"]" sp;
+ index_expr = "[" !"[" sp expr "]" sp;
call_expr = "(" sp ( expr ("," sp expr)* )? ("," sp)? ")" sp;
member_expr = "." sp ident sp;
cast_expr = "as" sp type;
diff --git a/chacha20_test.om b/chacha20_test.om
@@ -0,0 +1,52 @@
+func main(c:int,v:**byte,e:**byte) {
+ var _key: _chacha20_state;
+ var key: *byte;
+ var _nonce: _chacha20_state;
+ var nonce: *byte;
+ var _block: _chacha20_state;
+ var block: *byte;
+ var out: *file;
+
+ key = (&_key) as *byte;
+ nonce = (&_nonce) as *byte;
+ block = (&_block) as *byte;
+
+ bzero(key, sizeof(_key));
+ bzero(nonce, sizeof(_nonce));
+
+ out = nil;
+
+ chacha20_block(block, key, 0, nonce);
+ fputd(out, 1);
+ fputs(out, ":\n");
+ fxxd(out, block, 64);
+ fputc(out, '\n');
+
+ chacha20_block(block, key, 1, nonce);
+ fputd(out, 2);
+ fputs(out, ":\n");
+ fxxd(out, block, 64);
+ fputc(out, '\n');
+
+ key[31] = 1 as byte;
+ chacha20_block(block, key, 1, nonce);
+ fputd(out, 3);
+ fputs(out, ":\n");
+ fxxd(out, block, 64);
+ fputc(out, '\n');
+
+ key[1] = 0xff as byte;
+ key[31] = 0 as byte;
+ chacha20_block(block, key, 2, nonce);
+ fputd(out, 4);
+ fputs(out, ":\n");
+ fxxd(out, block, 64);
+ fputc(out, '\n');
+
+ key[1] = 0 as byte;
+ nonce[11] = 2 as byte;
+ chacha20_block(block, key, 0, nonce);
+ fputd(out, 5);
+ fputs(out, ":\n");
+ fxxd(out, block, 64);
+}
diff --git a/attic/check.py b/check.py
diff --git a/ed25519_test.om b/ed25519_test.om
@@ -0,0 +1,25 @@
+func main(argc: int, argv: **byte, envp: **byte) {
+ var _a: _ed25519_point;
+ var a: *byte;
+ var _b: _ed25519_point;
+ var b: *byte;
+ var _c: _ed25519_point;
+ var c: *byte;
+ var out: *file;
+
+ a = (&_a) as *byte;
+ b = (&_b) as *byte;
+ c = (&_c) as *byte;
+
+ out = nil;
+
+ assert(unhex(a, "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60") == 32, "unhex");
+ ed25519_sign(c, a, "", 0);
+ fxxd(out, c, 64);
+ fputc(out, '\n');
+
+ assert(unhex(a, "4ccd089b28ff96da9db6c346ec114e0f5b8a319f35aba624da8cf6ed4fb8a6fb") == 32, "unhex");
+ ed25519_sign(c, a, "r", 1);
+ fxxd(out, c, 64);
+ fputc(out, '\n');
+}
diff --git a/lib.om b/lib.om
@@ -496,3 +496,37 @@ func unescape(s: *byte, i: *int, len: int, ok: *int): int {
return 0;
}
}
+
+struct fxxdbuf {
+ a0: int;
+ a1: int;
+ a2: int;
+ a3: int;
+ a4: int;
+ a5: int;
+ a6: int;
+ a7: int;
+ a8: int;
+ a9: int;
+}
+
+func fxxd(out: *file, buf: *byte, n: int) {
+ var _line: fxxdbuf;
+ var line: *byte;
+ var i: int;
+
+ line = (&_line) as *byte;
+
+ i = 0;
+ loop {
+ if i > n {
+ break;
+ }
+
+ xxd_line(line, i, &buf[i], n - i);
+
+ fputs(out, line);
+
+ i = i + 16;
+ }
+}
diff --git a/poly1305_test.om b/poly1305_test.om
@@ -0,0 +1,58 @@
+func main(c: int, v: **byte, e: **byte) {
+ var _key: _poly1305_ctx;
+ var _text: _poly1305_ctx;
+ var _mac: _poly1305_ctx;
+ var key: *byte;
+ var text: *byte;
+ var mac: *byte;
+ var out: *file;
+
+ key = (&_key) as *byte;
+ text = (&_text) as *byte;
+ mac = (&_mac) as *byte;
+
+ out = nil;
+
+ bzero(key, 32);
+ bzero(text, 64);
+ bzero(mac, 32);
+
+ poly1305(mac, key, text, 64);
+ fxxd(out, mac, 16);
+
+ key[0] = 0x85 as byte;
+ key[1] = 0xd6 as byte;
+ key[2] = 0xbe as byte;
+ key[3] = 0x78 as byte;
+ key[4] = 0x57 as byte;
+ key[5] = 0x55 as byte;
+ key[6] = 0x6d as byte;
+ key[7] = 0x33 as byte;
+ key[8] = 0x7f as byte;
+ key[9] = 0x44 as byte;
+ key[10] = 0x52 as byte;
+ key[11] = 0xfe as byte;
+ key[12] = 0x42 as byte;
+ key[13] = 0xd5 as byte;
+ key[14] = 0x06 as byte;
+ key[15] = 0xa8 as byte;
+ key[16] = 0x01 as byte;
+ key[17] = 0x03 as byte;
+ key[18] = 0x80 as byte;
+ key[19] = 0x8a as byte;
+ key[20] = 0xfb as byte;
+ key[21] = 0x0d as byte;
+ key[22] = 0xb2 as byte;
+ key[23] = 0xfd as byte;
+ key[24] = 0x4a as byte;
+ key[25] = 0xbf as byte;
+ key[26] = 0xf6 as byte;
+ key[27] = 0xaf as byte;
+ key[28] = 0x41 as byte;
+ key[29] = 0x49 as byte;
+ key[30] = 0xf5 as byte;
+ key[31] = 0x1b as byte;
+
+ poly1305(mac, key, "Cryptographic Forum Research Group", 34);
+ fxxd(out, mac, 16);
+}
diff --git a/attic/pxe.asm b/pxe.asm
diff --git a/rsa.om b/rsa.om
@@ -0,0 +1,266 @@
+func rsa_mul(y: *int, a: *int, b: *int, n: int) {
+ var c: int;
+ var i: int;
+ var j: int;
+
+ i = 0;
+ loop {
+ if i == 2 * n {
+ break;
+ }
+
+ y[i] = 0;
+
+ i = i + 1;
+ }
+
+ i = 0;
+ loop {
+ if i == n {
+ break;
+ }
+
+ j = 0;
+ c = 0;
+ loop {
+ if j == n {
+ break;
+ }
+
+ c = c + (a[i] & (-1 >> 32)) * (b[j] & (-1 >> 32));
+ c = c + y[i + j];
+ y[i + j] = c & (-1 >> 32);
+
+ c = c >> 32;
+ j = j + 1;
+ }
+
+ j = j + i;
+
+ loop {
+ if j == 2 * n {
+ break;
+ }
+
+ c = c + y[j];
+ y[j] = c & (-1 >> 32);
+
+ j = j + 1;
+ c = c >> 32;
+ }
+
+ i = i + 1;
+ }
+}
+
+func rsa_trymod(r: *int, d: *int, q: int, n: int): int {
+ var i: int;
+ var a: int;
+ var s: int;
+
+ i = 0;
+ a = 0;
+ s = 1;
+ loop {
+ if i == n {
+ break;
+ }
+
+ a = a + (d[i] & (-1 >> 32)) * (q & (-1 >> 32));
+ s = s + ((~a) & (-1 >> 32));
+ s = s + (r[i] & (-1 >> 32));
+
+ i = i + 1;
+ a = a >> 32;
+ s = s >> 32;
+ }
+
+ s = s + ((~a) & (-1 >> 32));
+ s = s + (r[i] & (-1 >> 32));
+ s = s >> 32;
+
+ return ~s & ((q + (-1 >> 32)) >> 32);
+}
+
+func rsa_domod(r: *int, d: *int, q: int, n: int) {
+ var i: int;
+ var a: int;
+ var s: int;
+
+ i = 0;
+ a = 0;
+ s = 1;
+ loop {
+ if i == n {
+ break;
+ }
+
+ a = a + (d[i] & (-1 >> 32)) * (q & (-1 >> 32));
+ s = s + ((~a) & (-1 >> 32));
+ s = s + (r[i] & (-1 >> 32));
+ r[i] = s & (-1 >> 32);
+
+ i = i + 1;
+ a = a >> 32;
+ s = s >> 32;
+ }
+
+ s = s + ((~a) & (-1 >> 32));
+ s = s + (r[i] & (-1 >> 32));
+ r[i] = s & (-1 >> 32);
+}
+
+// Based on https://ridiculousfish.com/blog/posts/labor-of-division-episode-iv.html
+func rsa_mod(r: *int, x: *int, d: *int, n: int) {
+ var i: int;
+ var j: int;
+ var nd: int;
+ var k: int;
+ var h: int;
+ var q: int;
+ var a: int;
+
+ // Find the size of d
+ nd = n;
+ loop {
+ if (d[nd - 1] & (- 1 >> 32)) != 0 || nd == 0 {
+ break;
+ }
+
+ nd = nd - 1;
+ }
+
+ // Divide by a single word
+ if (nd == 1) {
+ i = 2 * n - 1;
+ a = 0;
+ loop {
+ a = ((a << 32) + (x[i] & (- 1 >> 32))) % (d[nd - 1] & (- 1 >> 32));
+ r[i] = 0;
+
+ if i == 0 {
+ break;
+ }
+
+ i = i - 1;
+ }
+
+ r[0] = a;
+ return;
+ }
+
+ // Find the fudge factor
+ h = d[nd - 1];
+ k = 0;
+ loop {
+ if h & (1 << 31) != 0 {
+ break;
+ }
+
+ h = h << 1;
+
+ k = k + 1;
+ }
+ h = h | ((d[nd - 2] & (- 1 >> 32)) << k) >> 32;
+
+ // Copy x to r
+ i = 0;
+ loop {
+ if i == 2 * n {
+ break;
+ }
+
+ r[i] = x[i] & (- 1 >> 32);
+
+ i = i + 1;
+ }
+ r[i] = 0;
+
+ i = 2 * n;
+ j = 2 * n - nd;
+ loop {
+ a = (r[i] << (k + 32))
+ | (r[i - 1] << k)
+ | ((r[i - 2] << k) >> 32);
+
+ // Compute guess
+ q = a / h;
+
+ // Bump it down
+ q = q - (q >> 32);
+
+ // Try twice since it is at most +2 from the lower guess
+ q = q - rsa_trymod(&r[j], d, q, n);
+ q = q - rsa_trymod(&r[j], d, q, n);
+
+ rsa_domod(&r[j], d, q, n);
+
+ if j == 0 {
+ break;
+ }
+
+ i = i - 1;
+ j = j - 1;
+ }
+}
+
+func rsa_sel(y: *int, x: *int, n: int, s: int) {
+ var i: int;
+
+ loop {
+ if i == n {
+ break;
+ }
+
+ y[i] = ((y[i] & ~s) | (x[i] & s)) & (-1 >> 32);
+
+ i = i + 1;
+ }
+}
+
+func rsa_pow(y: *int, x: *int, d: *int, m: *int, t: *int, n: int) {
+ var nd: int;
+ var i: int;
+ var e: int;
+
+ y[0] = 1;
+
+ i = 1;
+ loop {
+ if i == 2 * n {
+ break;
+ }
+
+ y[i] = 0;
+
+ i = i + 1;
+ }
+
+ nd = n - 1;
+ loop {
+ i = 0;
+ e = d[nd];
+ loop {
+ if i == 32 {
+ break;
+ }
+
+ rsa_mul(t, y, y, n);
+ rsa_mod(y, t, m, n);
+
+ rsa_mul(t, y, x, n);
+ rsa_mod(t, t, m, n);
+
+ rsa_sel(y, t, n, -((e >> 31) & 1));
+
+ i = i + 1;
+ e = e << 1;
+ }
+
+ if nd == 0 {
+ break;
+ }
+
+ nd = nd - 1;
+ }
+}
diff --git a/rsa_test.om b/rsa_test.om
@@ -0,0 +1,9 @@
+func main(argc: int, argv: **byte, envp: **byte) {
+ var y: *int;
+ var x: *int;
+ var d: *int;
+ var m: *int;
+ var t: *int;
+ var n: int;
+ rsa_pow(y, x, d, m, t, n);
+}
diff --git a/sha256_test.om b/sha256_test.om
@@ -0,0 +1,21 @@
+func main(argc: int, argv: **byte, envp: **byte) {
+ var d: _sha256_digest;
+ var digest: *byte;
+ var out: *file;
+ var alen: int;
+ var blen: int;
+ out = nil;
+ digest = (&d) as *byte;
+ if argc == 2 {
+ alen = strlen(argv[1]);
+ sha256(digest, argv[1], alen);
+ fxxd(out, digest, 32);
+ } else if argc == 3 {
+ alen = strlen(argv[1]);
+ blen = strlen(argv[2]);
+ sha256_hmac(digest, argv[1], alen, argv[2], blen);
+ fxxd(out, digest, 32);
+ } else {
+ exit(2);
+ }
+}
diff --git a/sha512_test.om b/sha512_test.om
@@ -0,0 +1,21 @@
+func main(argc: int, argv: **byte, envp: **byte) {
+ var d: _sha512_digest;
+ var digest: *byte;
+ var out: *file;
+ var alen: int;
+ var blen: int;
+ out = nil;
+ digest = (&d) as *byte;
+ if argc == 2 {
+ alen = strlen(argv[1]);
+ sha512(digest, argv[1], alen);
+ fxxd(out, digest, 64);
+ } else if argc == 3 {
+ alen = strlen(argv[1]);
+ blen = strlen(argv[2]);
+ sha512_hmac(digest, argv[1], alen, argv[2], blen);
+ fxxd(out, digest, 64);
+ } else {
+ exit(2);
+ }
+}
diff --git a/test.sh b/test.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+LIBS="peglib.om bufio.om lib.om alloc.om syscall.om"
+CRYPTO="ed25519.om sha512.om sha256.om chacha20.om poly1305.om aes.om rsa.om"
+
+./cc1 ${LIBS} ${CRYPTO} chacha20_test.om -o chacha20_test -n chacha20_test.lines -G chacha20_test.call
+./cc1 ${LIBS} ${CRYPTO} ed25519_test.om -o ed25519_test -n ed25519_test.lines -G ed25519_test.call
+./cc1 ${LIBS} ${CRYPTO} poly1305_test.om -o poly1305_test -n poly1305_test.lines -G poly1305_test.call
+./cc1 ${LIBS} ${CRYPTO} sha256_test.om -o sha256_test -n sha256_test.lines -G sha256_test.call
+./cc1 ${LIBS} ${CRYPTO} sha512_test.om -o sha512_test -n sha512_test.lines -G sha512_test.call
+./cc1 ${LIBS} ${CRYPTO} x25519_test.om -o x25519_test -n x25519_test.lines -G x25519_test.call
+./cc1 ${LIBS} ${CRYPTO} aes_test.om -o aes_test -n aes_test.lines -G aes_test.call
+./cc1 ${LIBS} ${CRYPTO} rsa_test.om -o rsa_test -n rsa_test.lines -G rsa_test.call
diff --git a/x25519_test.om b/x25519_test.om
@@ -0,0 +1,41 @@
+func main(argc: int, argv: **byte, envp: **byte) {
+ var _a: _ed25519_point;
+ var a: *byte;
+ var _b: _ed25519_point;
+ var b: *byte;
+ var _c: _ed25519_point;
+ var c: *byte;
+ var out: *file;
+
+ a = (&_a) as *byte;
+ b = (&_b) as *byte;
+ c = (&_c) as *byte;
+
+ out = nil;
+
+ assert(unhex(a, "e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c") == 32, "unhex");
+ assert(unhex(b, "a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4") == 32, "unhex");
+ assert(x25519(c, a, b), "decode");
+ fxxd(out, c, 32);
+ fputc(out, '\n');
+
+ x25519_base(a);
+ assert(unhex(b, "77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a") == 32, "unhex");
+ assert(x25519(c, a, b), "decode");
+ fxxd(out, c, 32);
+ fputc(out, '\n');
+
+ x25519_base(a);
+ assert(unhex(b, "5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb") == 32, "unhex");
+ assert(x25519(c, a, b), "decode");
+ fxxd(out, c, 32);
+ fputc(out, '\n');
+
+ x25519_base(a);
+ assert(unhex(b, "5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb") == 32, "unhex");
+ assert(x25519(c, a, b), "decode");
+ assert(unhex(b, "77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a") == 32, "unhex");
+ assert(x25519(c, c, b), "decode");
+ fxxd(out, c, 32);
+ fputc(out, '\n');
+}