os

An operating system
git clone https://erai.gay/code/os/
Log | Files | Refs | README | LICENSE

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:
M.build.yml | 1+
M.gitignore | 40+++++++++++-----------------------------
Aaes.om | 162+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aaes_test.om | 8++++++++
Dattic/aes.om | 162-------------------------------------------------------------------------------
Dattic/cc0.om | 5005-------------------------------------------------------------------------------
Dattic/cc3.l | 52----------------------------------------------------
Dattic/cc3.y | 152-------------------------------------------------------------------------------
Dattic/chacha20_test.om | 49-------------------------------------------------
Dattic/cout.om | 628-------------------------------------------------------------------------------
Dattic/ed25519_test.om | 22----------------------
Dattic/genlex.om | 1115-------------------------------------------------------------------------------
Dattic/lex1.om | 438-------------------------------------------------------------------------------
Dattic/parse1.om | 1446-------------------------------------------------------------------------------
Dattic/poly1305_test.om | 55-------------------------------------------------------
Dattic/rsa.om | 266-------------------------------------------------------------------------------
Dattic/sha256_test.om | 14--------------
Dattic/sha512_test.om | 14--------------
Dattic/x25519_test.om | 38--------------------------------------
Mbuild.sh | 3+--
Mcc0.c | 11++---------
Mcc3.om | 2+-
Achacha20_test.om | 52++++++++++++++++++++++++++++++++++++++++++++++++++++
Rattic/check.py -> check.py | 0
Aed25519_test.om | 25+++++++++++++++++++++++++
Mlib.om | 34++++++++++++++++++++++++++++++++++
Apoly1305_test.om | 58++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Rattic/pxe.asm -> pxe.asm | 0
Arsa.om | 266+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Arsa_test.om | 9+++++++++
Asha256_test.om | 21+++++++++++++++++++++
Asha512_test.om | 21+++++++++++++++++++++
Atest.sh | 13+++++++++++++
Ax25519_test.om | 41+++++++++++++++++++++++++++++++++++++++++
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'); +}