Commit Diff


commit - e0074095e24797bb794ffd465b0b2a6442caa8d9
commit + 9b4c94f07693bf4d51126899cbecf7ca5b3d904e
blob - 7de524159eeb3940ea7270e030f030511e494f59
blob + 1133285b38617bb7472f5063ad4ee08c6cd06f2c
--- tools/6c
+++ tools/6c
@@ -1,49 +1,118 @@
 #!/usr/local/bin/lua51
 
---[[
-This is the structure a token must follow. The token can be
-followed by a series of raw bytes if Length > 0.
+-----------------------------------------------------------------------
+-- TOKEN MATCHING
+-----------------------------------------------------------------------
+local mnemonics = { "mov", "cli", "hlt", "ret", "sti" }
 
-Token {
-	u32 Column;
-	u32 Line;
-	u16 Type;
-	u16 Length;
-}
+local symbols = { ",", "[", "]", "(", ")", "{", "}", "*", "/", "-",
+	"+", "!", "~", "#", "?", ";", ":" }
 
-Types are eight Opcodes, or C keywords
+local regs8 = { "al", "ah", "bl", "bh", "cl", "ch", "dl", "dh" }
 
-]]--
+local asmkwd = { "asm" }
 
-progname="6c"
+local tk_type = { }
+local count = 0
 
--- Program error
+for i = 1, #mnemonics do
+	count = count + 1
+	tk_type[mnemonics[i]] = count
+end
+
+for i = 1, #symbols do
+	count = count + 1
+	tk_type[symbols[i]] = count
+end
+
+for i = 1, #regs8 do
+	count = count + 1
+	tk_type[regs8[i]] = count
+end
+
+for i = 1, #asmkwd do
+	count = count + 1
+	tk_type[asmkwd[i]] = count
+end
+
+local function cincadd()
+	count = count + 1
+	return count
+end
+tk_type.hexadecimal = cincadd()
+tk_type.integer = cincadd()
+tk_type.id = cincadd()
+tk_type["\n"] = cincadd()
+
+-----------------------------------------------------------------------
+-- DEBUGING
+-----------------------------------------------------------------------
 local function perror(msg)
 	print(progname .. ": error: " .. msg)
 	os.exit(1)
 end
 
-if arg[1] == nil then
-	print("usage: " .. progname .. " input [output]")
-	os.exit(1)
+-----------------------------------------------------------------------
+-- BOOLEAN check
+-----------------------------------------------------------------------
+local function isnumber(n)
+	if n:match("[0-9]") then
+		return true
+	end
+	return false
 end
 
-if arg[2] == nil then
-	arg[2] = string.gsub(arg[1], "%.%w+$", ".6")
+local function issymbol(char)
+	for i,v in ipairs(symbols) do
+		if v == char then
+			return true
+		end
+	end
+	return false
 end
 
-src = io.open(arg[1], "r")
-dst = io.open(arg[2], "wb")
+local function gettokenkey(m)
+	for i, v in pairs(tk_type) do
+		if tk_type[i] == m.type then
+			return i
+		end
+	end
+	return nil
+end
 
-if src == nil then
-	perror("failed to open src");
+local function ismnemonic(m)
+	local key = gettokenkey(m)
+
+	if key == nil then
+		return false
+	end
+
+	for i,v in ipairs(mnemonics) do
+		if v == key then
+			return true
+		end
+	end
+	return false
 end
 
-if dst == nil then
-	perror("failed to open dst");
-	src:close()
+local function isregs8(m)
+	local key = gettokenkey(m)
+
+	if key == nil then
+		return false
+	end
+
+	for i,v in ipairs(regs8) do
+		if v == key then
+			return true
+		end
+	end
+	return false
 end
 
+-----------------------------------------------------------------------
+-- BITWISE OPERATIONS
+-----------------------------------------------------------------------
 local function brshift(value, bit)
 	return math.floor(value / (2 ^ bit))
 end
@@ -68,7 +137,42 @@ local function band(a, b)
 	return result
 end
 
-local function write_u32(value)
+local function bor(a, b)
+	local result = 0
+	local shift = 1
+
+	while a > 0 or b > 0 do
+		local r1 = a % 2
+		local r2 = b % 2
+
+		if r1 == 1 or r2 == 1 then
+			result = result + shift
+		end
+
+		a = math.floor(a / 2)
+		b = math.floor(b / 2)
+		shift = shift * 2
+	end
+
+	return result
+end
+
+-----------------------------------------------------------------------
+-- WRITE OPERATIONS
+-----------------------------------------------------------------------
+local function writeu8(dst, value)
+	local b = band(value, 0xff)
+	dst:write(string.char(b))
+end
+
+local function writeu16(dst, value)
+	local b2 = band(brshift(value, 8), 0xff)
+	local b1 = band(value, 0xff)
+
+	dst:write(string.char(b2, b1)) -- Little Endian x86
+end
+
+local function writeu32(dst, value)
 	local b4 = band(brshift(value, 24), 0xff)
 	local b3 = band(brshift(value, 16), 0xff)
 	local b2 = band(brshift(value, 8), 0xff)
@@ -77,117 +181,80 @@ local function write_u32(value)
 	dst:write(string.char(b4, b3, b2, b1)) -- Little Endian x86
 end
 
-local function write_u16(value)
-	local b2 = band(brshift(value, 8), 0xff)
-	local b1 = band(value, 0xff)
 
-	dst:write(string.char(b2, b1)) -- Little Endian x86
-end
+local function intval(intstr)
+	local len = #intstr
+	local res = 0
 
-local function write_u8(value)
-	local b = band(value, 0xff)
-	dst:write(string.char(b))
+	for i = 1, len do
+		local s = intstr:sub(len - i + 1, len - i + 1)
+		s = s * (10 ^ (i - 1))
+		res = res + s
+	end
+	return res
 end
 
-local TOKEN_ASM = 0
-local TOKEN_LEFT_CURLY_BRACKET = 1
-local TOKEN_RIGHT_CURLY_BRACKET = 2
-local TOKEN_MULTIPLY = 3
-local TOKEN_DIVIDE = 4
-local TOKEN_SUBTRACT = 5
-local TOKEN_ADD = 6
-local TOKEN_LEFT_SQUARE_BRACKET = 7
-local TOKEN_RIGHT_SQUARE_BRACKET = 8
-local TOKEN_LEFT_PARANTHESIS = 9
-local TOKEN_RIGHT_PARANTHESIS = 10
-local TOKEN_QUESTION = 11
-local TOKEN_EXCLAMATION = 12
-local TOKEN_TILDA = 13
-local TOKEN_PERIOD = 14
-local TOKEN_COLUMN = 15
-local TOKEN_INTEGER = 16
-local TOKEN_ID = 17
-local TOKEN_STRING = 18
-local TOKEN_SEMICOLON = 19
-local TOKEN_HASH = 20
-local TOKEN_COMMA = 21
-local TOKEN_HLT = 22
-local TOKEN_RET = 23
-local TOKEN_CLI = 24
-local TOKEN_STI = 25
-local TOKEN_AH = 26
-local TOKEN_AL = 27
-local TOKEN_BH = 28
-local TOKEN_BL = 29
-local TOKEN_CL = 30
-local TOKEN_CH = 31
-local TOKEN_DL = 32
-local TOKEN_DH = 33
-local TOKEN_MOV = 34
-local TOKEN_HEXADECIMAL = 35
+function hexval(hex)
+	local dig = hex:sub(3)
+	local len = #dig
+	local result = 0
 
-local function issymbol(char)
-	if char == "{" or
-	   char == "}" or
-	   char == "*" or
-	   char == "/" or
-	   char == "-" or
-	   char == "+" or
-	   char == "[" or
-	   char == "]" or
-	   char == "(" or
-	   char == ")" or
-	   char == "?" or
-	   char == "!" or
-	   char == "~" or
-	   char == "." or
-	   char == ":" or
-	   char == ";" or
-	   char == "," or
-	   char == "#" then
-		return true
+	for i = 1,len do
+		local d = dig:sub(i, i)
+
+		if d:lower() == "a" then
+			d = 10
+		elseif d:lower() == "b" then
+			d = 11
+		elseif d:lower() == "c" then
+			d = 12
+		elseif d:lower() == "d" then
+			d = 13
+		elseif d:lower() == "e" then
+			d = 14
+		elseif d:lower() == "f" then
+			d = 15
+		end
+
+		result = result + d * (16 ^ (len - i))
 	end
-	return false
+
+	return result
 end
+-----------------------------------------------------------------------
+-- Checking arguments and setting read and write file
+-----------------------------------------------------------------------
 
-local function isnumber(char)
-	if char == "0" or
-	   char == "1" or
-	   char == "2" or
-	   char == "3" or
-	   char == "4" or
-	   char == "5" or
-	   char == "6" or
-	   char == "7" or
-	   char == "8" or
-	   char == "9" then
-		return true
-	end
-	return false
+progname = "6c"
+local input = arg[1]
+local output = arg[2]
+
+if input == nil then
+	print("usage: 6c input output")
+	os.exit(1)
 end
 
-local function readid(line, s)
-	local len = #line
-	local buf = { }
+if output == nil then
+	output = string.gsub(input, "%.%w+$", ".6")
+end
 
-	for i = s, len do
-		local char = line:sub(i, i)
-		if char == " " then
-			break
-		end
+local src = io.open(input, "r")
+local dst = io.open(output, "wb")
 
-		if issymbol(char) == true then
-			break
-		end
+-----------------------------------------------------------------------
+-- Compiler functions
+-----------------------------------------------------------------------
+local function emittoken(line, col, type, len, raw)
+	writeu32(dst, line)
+	writeu32(dst, col)
+	writeu16(dst, type)
+	writeu16(dst, len)
 
-		if i == s and isnumber(char) == true then
-			break
+	if len > 0 then
+		for i = 1, len do
+			writeu8(dst, string.byte(raw:sub(i, i)))
 		end
-
-		table.insert(buf, char)
 	end
-
-	return table.concat(buf)
 end
 
 local function readint(line, s)
@@ -198,9 +265,13 @@ local function readint(line, s)
 	for i = s, len do
 		local char = line:sub(i, i)
 
+		if char == "" or char == " " or issymbol(char) then 
+			break 
+		end
+
 		if isnumber(char) == false then
-			if hex == false then
-				if char == "h" and (i - s) == 1 then
+			if hex == false and (i - s) == 1 then
+				if char == "h" then
 					local prefix = line:sub(i - 1, i - 1)
 
 					if prefix ~= "0" then
@@ -209,18 +280,10 @@ local function readint(line, s)
 
 					hex = true
 				else
-					if char ~= "" and char ~= " " then
-						print("illegal sufix for number line : " .. line)
-					end
+					perror("illegal character `" .. char .. "` line : " .. line)
 				end
 			else
-				if char == "" or char == " " then 
-					break 
-				end
-
-				if char ~= "a" and char ~= "A" and char ~= "b" and char ~= "B" and
-				   char ~= "c" and char ~= "C" and char ~= "d" and char ~= "D" and
-				   char ~= "e" and char ~= "E" and char ~= "f" and char ~= "F" then
+				if not char:match("[0-9a-fA-F]") then
 					perror("illegal sufix `" .. char .. "` for hexadecimal " .. line)
 				end
 			end
@@ -232,160 +295,93 @@ local function readint(line, s)
 	return table.concat(buf)
 end
 
-local nline = 0;
+local function readid(line, s)
+	local len = #line
+	local buf = { }
 
+	for i = s, len do
+		local char = line:sub(i, i)
+		if char == " " then
+			break
+		end
+
+		if issymbol(char) == true then
+			break
+		end
+
+		if i == s and isnumber(char) == true then
+			break
+		end
+
+		table.insert(buf, char)
+	end
+
+	return table.concat(buf)
+end
+
+-----------------------------------------------------------------------
+-- Tokenizing
+-----------------------------------------------------------------------
+
+local nline = 0
 while true do
-	line = src:read("*l");
-	if (line == nil) then
-		break;
+	local line = src:read("*l")
+	if line == nil then
+		break
 	end
 
 	local i = 1
-	local len = #line
-	local column = 0
+	local ncol = 0
 
-	while i <= len do
+	while i <= #line do
 		local char = line:sub(i, i)
-		local buf = { }
 
 		if issymbol(char) == true then
-			write_u32(nline)
-			write_u32(column)
-			if char == "{" then
-				write_u16(TOKEN_LEFT_CURLY_BRACKET)
-			elseif char == "}" then
-				write_u16(TOKEN_RIGHT_CURLY_BRACKET)
-			elseif char == "*" then
-				write_u16(TOKEN_MULTIPLY)
-			elseif char == "/" then
-				write_u16(TOKEN_DIVIDE)
-			elseif char == "." then
-				write_u16(TOKEN_PERIOD)
-			elseif char == ":" then
-				write_u16(TOKEN_COLUMN)
-			elseif char == "[" then
-				write_u16(TOKEN_LEFT_SQUARE_BRACKET)
-			elseif char == "]" then
-				write_u16(TOKEN_RIGHT_SQUARE_BRACKET)
-			elseif char == "(" then
-				write_u16(TOKEN_LEFT_PARANTHESIS)
-			elseif char == ")" then
-				write_u16(TOKEN_RIGHT_PARANTHESIS)
-			elseif char == ";" then
-				write_u16(TOKEN_SEMICOLON)
-			elseif char == "#" then
-				write_u16(TOKEN_HASH)
-			elseif char == "," then
-				write_u16(TOKEN_COMMA)
-			else
-				print("Unknown symbol : " .. char)
+			if tk_type[char] == nil then
+				perror("Unknown symbol `" .. char .. "`")
 			end
-
-			write_u16(0)
+			emittoken(nline, ncol, tk_type[char], 0, nil)
 			i = i + 1
-
-		elseif char == " " or char == "\t" then
-			i = i + 1
-
-		elseif char == "\n" then
-			i = i + 1
-
-		elseif isnumber(char) then
-			local sint = readint(line, i)
+		elseif isnumber(char) == true then
+			local data = readint(line, i)
 			local ishex = false
 
-			if sint:sub(2, 2) == "h" then
+			if data:sub(2, 2) == "h" then
 				ishex = true
 			end
 
-			local j = 1
-			write_u32(nline)
-			write_u32(column)
 			if ishex == true then
-				write_u16(TOKEN_HEXADECIMAL)
+				emittoken(nline, ncol, tk_type.hexadecimal, #data, data)
 			else
-				write_u16(TOKEN_INTEGER)
+				emittoken(nline, ncol, tk_type.integer, #data, data)
 			end
-			write_u16(#sint)
-			i = i + #sint
-
-			while j <= #sint do
-				local c = sint:sub(j, j)
-				write_u8(string.byte(c))
-				j = j + 1
-			end
-
-		elseif (char:match(".")) then
+			i = i + #data
+		elseif char == " " or char == "\t" then
+			i = i + 1
+		else
 			local id = readid(line, i)
+			if #id == 0 then
+				break
+			end
 
-			write_u32(nline)
-			write_u32(column)
-			if id == "asm" then
-				write_u16(TOKEN_ASM)
-				write_u16(0)
-			elseif id == "hlt" then
-				write_u16(TOKEN_HLT)
-				write_u16(0)
-			elseif id == "ret" then
-				write_u16(TOKEN_RET)
-				write_u16(0)
-			elseif id == "cli" then
-				write_u16(TOKEN_CLI)
-				write_u16(0)
-			elseif id == "sti" then
-				write_u16(TOKEN_STI)
-				write_u16(0)
-			elseif id == "ah" then
-				write_u16(TOKEN_AH)
-				write_u16(0)
-			elseif id == "al" then
-				write_u16(TOKEN_AL)
-				write_u16(0)
-			elseif id == "bh" then
-				write_u16(TOKEN_BH)
-				write_u16(0)
-			elseif id == "bl" then
-				write_u16(TOKEN_BL)
-				write_u16(0)
-			elseif id == "ch" then
-				write_u16(TOKEN_CH)
-				write_u16(0)
-			elseif id == "cl" then
-				write_u16(TOKEN_CL)
-				write_u16(0)
-			elseif id == "dh" then
-				write_u16(TOKEN_DH)
-				write_u16(0)
-			elseif id == "dl" then
-				write_u16(TOKEN_DL)
-				write_u16(0)
-			elseif id == "mov" then
-				write_u16(TOKEN_MOV)
-				write_u16(0)
+			if tk_type[id] == nil then
+				emittoken(nline, ncol, tk_type.id, #id, id)
 			else
-				local j = 1
-				write_u16(TOKEN_ID)
-				write_u16(#id)
-
-				-- Raw bytes
-				while j <= #id do
-					local c = id:sub(j, j)
-					write_u8(string.byte(c))
-					j = j + 1
-				end
+				emittoken(nline, ncol, tk_type[id], 0, nil)
 			end
+
 			i = i + #id
-		else
-			i = i + 1
 		end
 
-		column = i
+		ncol = i
 	end
 
+	emittoken(nline, ncol, tk_type["\n"], 0, nil)
 	nline = nline + 1
 end
 
+-----------------------------------------------------------------------
+-- Close files
+-----------------------------------------------------------------------
 src:close()
 dst:close()
-
-print(progname .. ": " .. arg[1] .. " -> " .. arg[2])
blob - ce8ce69a13ac2aa9f4ce553f4fe23518d06d60e8
blob + 116e3a97da138a8770841c72c42d761751f72500
--- tools/6l
+++ tools/6l
@@ -1,33 +1,118 @@
 #!/usr/local/bin/lua51
 
-progname = "6l"
+-----------------------------------------------------------------------
+-- TOKEN MATCHING
+-----------------------------------------------------------------------
+local mnemonics = { "mov", "cli", "hlt", "ret", "sti" }
 
-if (arg[1] == nil) then
-	print("usage: " .. progname .. " [file ...]")
-	os.exit(1)
+local symbols = { ",", "[", "]", "(", ")", "{", "}", "*", "/", "-",
+	"+", "!", "~", "#", "?", ";", ":" }
+
+local regs8 = { "al", "ah", "bl", "bh", "cl", "ch", "dl", "dh" }
+
+local asmkwd = { "asm" }
+
+local tk_type = { }
+local count = 0
+
+for i = 1, #mnemonics do
+	count = count + 1
+	tk_type[mnemonics[i]] = count
 end
 
-if arg[2] == nil then
-	arg[2] = "6." ..string.gsub(arg[1], "%.%w+$", "")
+for i = 1, #symbols do
+	count = count + 1
+	tk_type[symbols[i]] = count
 end
 
+for i = 1, #regs8 do
+	count = count + 1
+	tk_type[regs8[i]] = count
+end
+
+for i = 1, #asmkwd do
+	count = count + 1
+	tk_type[asmkwd[i]] = count
+end
+
+local function cincadd()
+	count = count + 1
+	return count
+end
+tk_type.hexadecimal = cincadd()
+tk_type.integer = cincadd()
+tk_type.id = cincadd()
+tk_type["\n"] = cincadd()
+
+-----------------------------------------------------------------------
+-- DEBUGING
+-----------------------------------------------------------------------
 local function perror(msg)
 	print(progname .. ": error: " .. msg)
 	os.exit(1)
 end
 
-src = io.open(arg[1], "rb")
+-----------------------------------------------------------------------
+-- BOOLEAN check
+-----------------------------------------------------------------------
+local function isnumber(n)
+	if n:match("[0-9]") then
+		return true
+	end
+	return false
+end
 
-if src == nil then
-	perror("failed to open " .. arg[1])
+local function issymbol(char)
+	for i,v in ipairs(symbols) do
+		if v == char then
+			return true
+		end
+	end
+	return false
 end
 
-dst = io.open(arg[2], "wb")
+local function gettokenkey(m)
+	for i, v in pairs(tk_type) do
+		if tk_type[i] == m.type then
+			return i
+		end
+	end
+	return nil
+end
 
-if dst == nil then
-	perror("failed to open " .. arg[2])
+local function ismnemonic(m)
+	local key = gettokenkey(m)
+
+	if key == nil then
+		return false
+	end
+
+	for i,v in ipairs(mnemonics) do
+		if v == key then
+			return true
+		end
+	end
+	return false
 end
 
+local function isregs8(m)
+	local key = gettokenkey(m)
+
+	if key == nil then
+		return false
+	end
+
+	for i,v in ipairs(regs8) do
+		if v == key then
+			return true
+		end
+	end
+	return false
+end
+
+-----------------------------------------------------------------------
+-- BITWISE OPERATIONS
+-----------------------------------------------------------------------
 local function brshift(value, bit)
 	return math.floor(value / (2 ^ bit))
 end
@@ -36,6 +121,22 @@ local function blshift(value, bit)
 	return value * (2 ^ bit)
 end
 
+local function band(a, b)
+	local result = 0
+	local bitval = 1
+
+	while a > 0 and b > 0 do
+		if (a % 2 == 1) and (b % 2 == 1) then
+			result = result + bitval
+		end
+		a = math.floor(a / 2)
+		b = math.floor(b / 2)
+		bitval = bitval * 2
+	end
+
+	return result
+end
+
 local function bor(a, b)
 	local result = 0
 	local shift = 1
@@ -56,80 +157,41 @@ local function bor(a, b)
 	return result
 end
 
---[[
+-----------------------------------------------------------------------
+-- WRITE OPERATIONS
+-----------------------------------------------------------------------
+local function writeu8(dst, value)
+	local b = band(value, 0xff)
+	dst:write(string.char(b))
+end
 
-Token {
-	u32 Line;
-	u32 Column;
-	u16 Type;
-	u16 Length;
-}
+local function writeu16(dst, value)
+	local b2 = band(brshift(value, 8), 0xff)
+	local b1 = band(value, 0xff)
 
-]]--
+	dst:write(string.char(b2, b1)) -- Little Endian x86
+end
 
-local TOKEN_ASM = 0
-local TOKEN_LEFT_CURLY_BRACKET = 1
-local TOKEN_RIGHT_CURLY_BRACKET = 2
-local TOKEN_MULTIPLY = 3
-local TOKEN_DIVIDE = 4
-local TOKEN_SUBTRACT = 5
-local TOKEN_ADD = 6
-local TOKEN_LEFT_SQUARE_BRACKET = 7
-local TOKEN_RIGHT_SQUARE_BRACKET = 8
-local TOKEN_LEFT_PARANTHESIS = 9
-local TOKEN_RIGHT_PARANTHESIS = 10
-local TOKEN_QUESTION = 11
-local TOKEN_EXCLAMATION = 12
-local TOKEN_TILDA = 13
-local TOKEN_PERIOD = 14
-local TOKEN_COLUMN = 15
-local TOKEN_INTEGER = 16
-local TOKEN_ID = 17
-local TOKEN_STRING = 18
-local TOKEN_SEMICOLON = 19
-local TOKEN_HASH = 20
-local TOKEN_COMMA = 21
-local TOKEN_HLT = 22
-local TOKEN_RET = 23
-local TOKEN_CLI = 24
-local TOKEN_STI = 25
-local TOKEN_AH = 26
-local TOKEN_AL = 27
-local TOKEN_BH = 28
-local TOKEN_BL = 29
-local TOKEN_CL = 30
-local TOKEN_CH = 31
-local TOKEN_DL = 32
-local TOKEN_DH = 33
-local TOKEN_MOV = 34
-local TOKEN_HEXADECIMAL = 35
+local function writeu32(dst, value)
+	local b4 = band(brshift(value, 24), 0xff)
+	local b3 = band(brshift(value, 16), 0xff)
+	local b2 = band(brshift(value, 8), 0xff)
+	local b1 = band(value, 0xff)
 
-local asm = {
-	hlt = 0xF4,
-	ret = 0xC3, -- Near return
-	cli = 0xFA,
-	sti = 0xFB,
-}
+	dst:write(string.char(b4, b3, b2, b1)) -- Little Endian x86
+end
 
-local MODE_NONE = 0
-local MODE_ASM = 1
 
-function readtoken()
-	local header = src:read(12)
+local function intval(intstr)
+	local len = #intstr
+	local res = 0
 
-	if header == nil then
-		return nil
+	for i = 1, len do
+		local s = intstr:sub(len - i + 1, len - i + 1)
+		s = s * (10 ^ (i - 1))
+		res = res + s
 	end
-
-	local b = { string.byte(header, 1, 12) }
-
-	local line = b[4] + blshift(b[3], 8) + blshift(b[2], 16) + blshift(b[1], 24)
-	local col = b[8] + blshift(b[7], 8) + blshift(b[6], 16) + blshift(b[5], 24)
-	local type = b[10] + blshift(b[9], 8)
-	local length = b[12] + blshift(b[11], 8)
-	local raw = src:read(length)
-
-	return { column = col, line = line, type = type, length = length, raw = raw }
+	return res
 end
 
 function hexval(hex)
@@ -159,204 +221,228 @@ function hexval(hex)
 
 	return result
 end
+-----------------------------------------------------------------------
+-- Checking arguments
+-----------------------------------------------------------------------
+progname = "6l"
+local input = arg[1]
+local output = arg[2]
 
-local mode = MODE_NONE
-local brace_depth = 0
-local begin = src:seek("cur")
+local symbol_table = { }
+local offset = 0
+local parser = {
+	inasm = false, -- In Assembly
+	insec = false, -- In Section
+}
 
-while true do
-	local token = readtoken()
-	if token == nil then
-		break
+if input == nil then
+	print("usage: 6l input output")
+	os.exit(1)
+end
+
+if output == nil then
+	output = string.gsub(input, "%.%w+$", "")
+end
+
+local src = io.open(input, "rb")
+if src == nil then
+	perror("failed to open `" .. input .. "`")
+end
+
+local dst = io.open("6." .. output, "wb")
+if dst == nil then
+	perror("failed to open `" .. output .. "`")
+end
+
+-----------------------------------------------------------------------
+-- Utility
+-----------------------------------------------------------------------
+local function readhdr()
+	local hdr = src:read(12)
+	if hdr == nil then
+		return nil
 	end
 
-	-- Syntax check
-	if token.type == TOKEN_ASM then
-		if mode == MODE_ASM then
-			perror("error: nested asm attempt at line " .. token.line .. " column " .. token.column)
-			break
-		end
+	local b = { string.byte((hdr), 1, 12) }
 
-		local next = readtoken()
-		if next == nil or next.type ~= TOKEN_LEFT_CURLY_BRACKET then
-			perror("error: missing '{' after asm at line " .. token.line .. " column " .. token.column)
-			break
-		end
+	local line =	b[4] + blshift(b[3], 8) + blshift(b[2], 16) + blshift(b[1], 24)
+	local col = 	b[8] + blshift(b[7], 8) + blshift(b[6], 16) + blshift(b[5], 24)
+	local type = 	b[10] + blshift(b[9], 8)
+	local len = 	b[12] + blshift(b[11], 8)
+	local raw =		nil
 
-		mode = MODE_ASM
-	elseif token.type == TOKEN_HLT then
-		if mode ~= MODE_ASM then
-			perror("error: hlt instruction outside asm block at line " .. token.line .. " column " ..
-				token.column)
-		end
+	if len > 0 then raw = src:read(len) end
+	return { line = line, col = col, type = type, len = len, raw = raw }
+end
 
-		local next = readtoken()
+-- This functions reads an asm line and tells if its a label or instructions
+-- If the return type is instructions, it will tell if its imm8, r8, etc
+--
+-- To keep the assembler simple we will only allow 0-3 operands. More is simply
+-- silly and unecessary for the goal.
+local ASM_UNKNOWN = 0
+local ASM_LABEL = 1
+local ASM_INSTRUCTION = 2
+local ASM_R8 = 3
+local ASM_IMM8 = 4
 
-		if next ~= nil and next.line == token.line then
-			perror("error: illegal token next to hlt on line " .. token.line .. " column " .. 
-				token.column)
+local function operlyze(op, ret)
+	if isregs8(op) == true then
+		ret.opcount = 1
+		table.insert(ret.details, ASM_R8)
+	elseif op.type == tk_type.integer then
+		ret.opcount = 1
+		local val = intval(op.raw)
+
+		if val < 256 then
+			table.insert(ret.details, ASM_IMM8)
+		else
+			perror("operand 1 of instruction on line " .. op.line .. " is too big!")
 		end
-	elseif token.type == TOKEN_RET then
-		if mode ~= MODE_ASM then
-			perror("error: ret instruction out of asm block at line " .. token.line .. " column " ..
-				token.column)
-		end
+	elseif op.type == tk_type.hexadecimal then
+		ret.opcount = 1
+		local val = hexval(op.raw)
 
-		local next = readtoken()
-		if next ~= nil and next.line == token.line then
-			perror("error: illegal token after ret on line " .. token.line " .. column " ..
-				token.column)
+		if val < 256 then
+			table.insert(ret.details, ASM_IMM8)
+		else
+			perror("operand 1 of instruction on line " .. op.line .. " is too big!")
 		end
-	elseif token.type == TOKEN_CLI then
-		if mode ~= MODE_ASM then
-			perror("error: cli instruction out of asm block at line " .. token.line .. " column " ..
-				token.column)
-		end
+	elseif op.type == tk_type["\n"] then
+		ret.opcount = 0
+	else
+		perror("unknown operand `" .. gettokenkey(op) .. "` at line " .. op.line)
+	end
+end
 
-		local next = readtoken()
-		if next ~= nil and next.line == token.line then
-			perror("error: illegal token after cli on line " .. token.line " .. column " ..
-				token.column)
+local function asmlyze(first)
+	if ismnemonic(first) == true then
+		local ret = { 
+			type = ASM_INSTRUCTION,
+			opcount = 0,
+			details = { }
+		}
+
+		local op1 = readhdr()
+		operlyze(op1, ret)
+
+		if ret.opcount == 0 then
+			return ret
 		end
-	elseif token.type == TOKEN_STI then
-		if mode ~= MODE_ASM then
-			perror("error: sti instruction out of asm block at line " .. token.line .. " column " ..
-				token.column)
-		end
 
-		local next = readtoken()
-		if next ~= nil and next.line == token.line then
-			perror("error: illegal token after sti on line " .. token.line " .. column " ..
-				token.column)
+		local com = readhdr()
+
+		if com.type == tk_type["\n"] then
+			return ret
 		end
 
-	elseif token.type == TOKEN_MOV then
-		if mode ~= MODE_ASM then
-			perror("error: sti instruction out of asm block at line " .. token.line .. " column " ..
-				token.column)
+		if com.type ~= tk_type[","] then
+			perror("missing comma next to first operand on line " .. op1.line)
 		end
 
-		local op1 = readtoken()
+		local op2 = readhdr()
+		operlyze(op2, ret)
 
-		if op1.type ~= TOKEN_AL and op1.type ~= TOKEN_AH and op1.type ~= TOKEN_BL and
-		   op1.type ~= TOKEN_BH and op1.type ~= TOKEN_CH and
-		   op1.type ~= TOKEN_CL and op1.type ~= TOKEN_DH and
-		   op1.type ~= TOKEN_DL then
-			perror("illegal first operand for mov at line " .. token.line .. " column " ..
-				token.column)
+		if ret.opcount == 0 then
+			return ret
 		end
 
-		local comma = readtoken()
+		com = readhdr()
+		if com.type == tk_type["\n"] then
+			return ret
+		end
 
-		if comma.type ~= TOKEN_COMMA then
-			perror("missing comma next to first operand line " .. token.line .. " column " ..
-				token.column)
+		if com.type ~= tk_type[","] then
+			perror("missing comma next to second operand on line " .. op1.line)
 		end
 
-		local op2 = readtoken()
+		local op3 = readhdr()
+		operlyze(op3, ret)
 
-		if op2.type ~= TOKEN_AL and op2.type ~= TOKEN_AH and op2.type ~= TOKEN_BL and
-		   op2.type ~= TOKEN_BH and op2.type ~= TOKEN_CH and
-		   op2.type ~= TOKEN_CL and op2.type ~= TOKEN_DH and
-		   op2.type ~= TOKEN_DL and op2.type ~= TOKEN_HEXADECIMAL then
-			perror("illegal second operand for mov at line " .. token.line .. " column " ..
-				token.column)
+		if ret.opcount == 0 then
+			return ret
 		end
 
-		-- Checking if hex value is to high: mov r8, imm8
-		if op2.type == TOKEN_HEXADECIMAL and 
-		  (op1.type == TOKEN_AH or op1.type == TOKEN_AL or
-		   op1.type == TOKEN_BH or op1.type == TOKEN_BL or
-		   op1.type == TOKEN_CH or op1.type == TOKEN_CL or
-		   op1.type == TOKEN_DH or op1.type == TOKEN_DL) then
-			if hexval(op2.raw) > 255 then
-				perror("hexvalue too high at line " .. token.line .. " column " .. token.column)
+		local nl = readhdr()
+		if nl.type == tk_type["\n"] then
+			return ret
+		end
+
+		perror("can only take up to 3 operands instructions. Line " .. first.line)
+
+	else
+		if first.type == tk_type.id then
+			local col = readhdr()
+			if col.type ~= tk_type[":"] then
+				perror("missing colon next to " .. gettokenkey(first) .. " line " .. first.line)
+			else
+				return { type = ASM_LABEL }
 			end
+			perror("Unknown instruction at line " .. first.line)
+		else
+			perror("illegal first element in instruction from line " .. first.line)
 		end
 	end
 end
 
-src:seek("set", begin)
-
+-----------------------------------------------------------------------
+-- 1st pass (syntax check and symbol table)
+-----------------------------------------------------------------------
 while true do
-	local token = readtoken()
-	if token == nil then
+	local hdr = readhdr()	
+	if hdr == nil then
 		break
 	end
 
-	if token.type == TOKEN_HLT then
-		dst:write(string.char(asm.hlt))
-	elseif token.type == TOKEN_RET then
-		dst:write(string.char(asm.ret))
-	elseif token.type == TOKEN_CLI then
-		dst:write(string.char(asm.cli))
-	elseif token.type == TOKEN_STI then
-		dst:write(string.char(asm.sti))
-	elseif token.type == TOKEN_MOV then
-		local op1 = readtoken()
-		readtoken() -- Comma
-		local op2 = readtoken()
+	if parser.inasm == true then
+		if hdr.type == tk_type["asm"] then
+			perror("illegal nested asm keyword at line " .. hdr.line .. " column " .. hdr.col)
+		elseif hdr.type == tk_type["}"] then
+			parser.inasm = false
+		else
+			if hdr.type ~= tk_type["\n"] then
+				local inst = asmlyze(hdr)
 
-		if op1.type == TOKEN_AL then
-			if op2.type == TOKEN_HEXADECIMAL then
-				local opcode = { hexval("0hB0") + tonumber("000", 2), hexval(op2.raw) }
+				if inst.type == ASM_INSTRUCTION then
+					if hdr.type == tk_type["mov"] then
+						-- mov r8, r8
+						if inst.details[1] == ASM_R8 and inst.details[2] == ASM_R8 then
+							offset = offset + 2
 
-				dst:write(string.char(opcode[1]))
-				dst:write(string.char(opcode[2]))
-			end
-		elseif op1.type == TOKEN_AH then
-			if op2.type == TOKEN_HEXADECIMAL then
-				local opcode = { hexval("0hB0") + tonumber("100", 2), hexval(op2.raw) }
+						-- mov r8, imm8
+						elseif inst.details[1] == ASM_R8 and inst.details[2] == ASM_IMM8 then
+							offset = offset + 2
 
-				dst:write(string.char(opcode[1]))
-				dst:write(string.char(opcode[2]))
+						-- huh?
+						else
+							perror("invalid instruction at line " .. hdr.line)
+						end
+					end
+				-- Add symbol table
+				elseif inst.type == ASM_LABEL then
+					symbol_table[hdr.raw] = offset
+				else
+					perror("Unknown instruction line " .. hdr.line)
+				end
 			end
-		elseif op1.type == TOKEN_BL then
-			if op2.type == TOKEN_HEXADECIMAL then
-				local opcode = { hexval("0hB0") + tonumber("011", 2), hexval(op2.raw) }
-
-				dst:write(string.char(opcode[1]))
-				dst:write(string.char(opcode[2]))
+		end
+	else
+		if hdr.type == tk_type["asm"] then
+			local next = readhdr()
+			if next.type ~= tk_type["{"] then
+				perror("missing { after asm, line " .. hdr.line .. " column " .. hdr.col)
 			end
-		elseif op1.type == TOKEN_BH then
-			if op2.type == TOKEN_HEXADECIMAL then
-				local opcode = { hexval("0hB0") + tonumber("111", 2), hexval(op2.raw) }
-
-				dst:write(string.char(opcode[1]))
-				dst:write(string.char(opcode[2]))
-			end
-		elseif op1.type == TOKEN_CL then
-			if op2.type == TOKEN_HEXADECIMAL then
-				local opcode = { hexval("0hB0") + tonumber("001", 2), hexval(op2.raw) }
-
-				dst:write(string.char(opcode[1]))
-				dst:write(string.char(opcode[2]))
-			end
-		elseif op1.type == TOKEN_CH then
-			if op2.type == TOKEN_HEXADECIMAL then
-				local opcode = { hexval("0hB0") + tonumber("101", 2), hexval(op2.raw) }
-
-				dst:write(string.char(opcode[1]))
-				dst:write(string.char(opcode[2]))
-			end
-		elseif op1.type == TOKEN_DL then
-			if op2.type == TOKEN_HEXADECIMAL then
-				local opcode = { hexval("0hB0") + tonumber("010", 2), hexval(op2.raw) }
-
-				dst:write(string.char(opcode[1]))
-				dst:write(string.char(opcode[2]))
-			end
-		elseif op1.type == TOKEN_DH then
-			if op2.type == TOKEN_HEXADECIMAL then
-				local opcode = { hexval("0hB0") + tonumber("110", 2), hexval(op2.raw) }
-
-				dst:write(string.char(opcode[1]))
-				dst:write(string.char(opcode[2]))
-			end
+			parser.inasm = true
 		end
 	end
 end
 
+-----------------------------------------------------------------------
+-- 2nd pass binary generation
+-----------------------------------------------------------------------
+
+-----------------------------------------------------------------------
+-- Closing files
+-----------------------------------------------------------------------
 src:close()
 dst:close()
-print(arg[1] .. " -> " .. arg[2])
blob - 17dc1369b1522cc6139fcb7b47f9086f35c4d8bb (mode 644)
blob + /dev/null
--- tools/boot.c
+++ /dev/null
@@ -1,4 +0,0 @@
-asm {
-_start:
-	ret
-}
blob - /dev/null
blob + 846d2fda3cde69a0ef32cbed3930c60c8c5bb3da (mode 644)
--- /dev/null
+++ tools/boot.sc
@@ -0,0 +1,9 @@
+asm {
+_start:
+	mov al, 0h10
+	mov ah, 22
+	ret
+main:
+	hlt
+	cli
+}
blob - /dev/null
blob + 1a239eae8c59bda6d3eae8bd932b95f37299a372 (mode 755)
--- /dev/null
+++ tools/build.sh
@@ -0,0 +1,18 @@
+#!/bin/ksh
+
+# The goal of this script is to combine lua files into
+# a single executable script
+
+COMPILER=6c
+LINKER=6l
+
+# compiler
+echo "#!/usr/local/bin/lua51\n" > $COMPILER
+cat util.lua compiler.lua >> $COMPILER
+
+# linker
+echo "#!/usr/local/bin/lua51\n" > $LINKER
+cat util.lua linker.lua >> $LINKER
+
+chmod +x $COMPILER
+chmod +x $LINKER
blob - /dev/null
blob + 71f6edaaccf35a7ecad23def99747b4524d30cd9 (mode 644)
--- /dev/null
+++ tools/compiler.lua
@@ -0,0 +1,164 @@
+-----------------------------------------------------------------------
+-- Checking arguments and setting read and write file
+-----------------------------------------------------------------------
+
+progname = "6c"
+local input = arg[1]
+local output = arg[2]
+
+if input == nil then
+	print("usage: 6c input output")
+	os.exit(1)
+end
+
+if output == nil then
+	output = string.gsub(input, "%.%w+$", ".6")
+end
+
+local src = io.open(input, "r")
+local dst = io.open(output, "wb")
+
+-----------------------------------------------------------------------
+-- Compiler functions
+-----------------------------------------------------------------------
+local function emittoken(line, col, type, len, raw)
+	writeu32(dst, line)
+	writeu32(dst, col)
+	writeu16(dst, type)
+	writeu16(dst, len)
+
+	if len > 0 then
+		for i = 1, len do
+			writeu8(dst, string.byte(raw:sub(i, i)))
+		end
+	end
+end
+
+local function readint(line, s)
+	local len = #line
+	local buf = { }
+	local hex = false
+
+	for i = s, len do
+		local char = line:sub(i, i)
+
+		if char == "" or char == " " or issymbol(char) then 
+			break 
+		end
+
+		if isnumber(char) == false then
+			if hex == false and (i - s) == 1 then
+				if char == "h" then
+					local prefix = line:sub(i - 1, i - 1)
+
+					if prefix ~= "0" then
+						perror("illegal token `" .. prefix .. "` next to number : " .. line)
+					end
+
+					hex = true
+				else
+					perror("illegal character `" .. char .. "` line : " .. line)
+				end
+			else
+				if not char:match("[0-9a-fA-F]") then
+					perror("illegal sufix `" .. char .. "` for hexadecimal " .. line)
+				end
+			end
+		end
+
+		table.insert(buf, char)
+	end
+
+	return table.concat(buf)
+end
+
+local function readid(line, s)
+	local len = #line
+	local buf = { }
+
+	for i = s, len do
+		local char = line:sub(i, i)
+		if char == " " then
+			break
+		end
+
+		if issymbol(char) == true then
+			break
+		end
+
+		if i == s and isnumber(char) == true then
+			break
+		end
+
+		table.insert(buf, char)
+	end
+
+	return table.concat(buf)
+end
+
+-----------------------------------------------------------------------
+-- Tokenizing
+-----------------------------------------------------------------------
+
+local nline = 0
+while true do
+	local line = src:read("*l")
+	if line == nil then
+		break
+	end
+
+	local i = 1
+	local ncol = 0
+
+	while i <= #line do
+		local char = line:sub(i, i)
+
+		if issymbol(char) == true then
+			if tk_type[char] == nil then
+				perror("Unknown symbol `" .. char .. "`")
+			end
+			emittoken(nline, ncol, tk_type[char], 0, nil)
+			i = i + 1
+		elseif isnumber(char) == true then
+			local data = readint(line, i)
+			local ishex = false
+
+			if data:sub(2, 2) == "h" then
+				ishex = true
+			end
+
+			if ishex == true then
+				emittoken(nline, ncol, tk_type.hexadecimal, #data, data)
+			else
+				emittoken(nline, ncol, tk_type.integer, #data, data)
+			end
+			i = i + #data
+		elseif char == " " or char == "\t" then
+			i = i + 1
+		else
+			local id = readid(line, i)
+			if #id == 0 then
+				break
+			end
+
+			if tk_type[id] == nil then
+				emittoken(nline, ncol, tk_type.id, #id, id)
+			else
+				emittoken(nline, ncol, tk_type[id], 0, nil)
+			end
+
+			i = i + #id
+		end
+
+		ncol = i
+	end
+
+	emittoken(nline, ncol, tk_type["\n"], 0, nil)
+	nline = nline + 1
+end
+
+-----------------------------------------------------------------------
+-- Close files
+-----------------------------------------------------------------------
+src:close()
+dst:close()
blob - /dev/null
blob + 4fd03b00959bb3a8a3763042c0eddde8adaa01e0 (mode 644)
--- /dev/null
+++ tools/linker.lua
@@ -0,0 +1,225 @@
+-----------------------------------------------------------------------
+-- Checking arguments
+-----------------------------------------------------------------------
+progname = "6l"
+local input = arg[1]
+local output = arg[2]
+
+local symbol_table = { }
+local offset = 0
+local parser = {
+	inasm = false, -- In Assembly
+	insec = false, -- In Section
+}
+
+if input == nil then
+	print("usage: 6l input output")
+	os.exit(1)
+end
+
+if output == nil then
+	output = string.gsub(input, "%.%w+$", "")
+end
+
+local src = io.open(input, "rb")
+if src == nil then
+	perror("failed to open `" .. input .. "`")
+end
+
+local dst = io.open("6." .. output, "wb")
+if dst == nil then
+	perror("failed to open `" .. output .. "`")
+end
+
+-----------------------------------------------------------------------
+-- Utility
+-----------------------------------------------------------------------
+local function readhdr()
+	local hdr = src:read(12)
+	if hdr == nil then
+		return nil
+	end
+
+	local b = { string.byte((hdr), 1, 12) }
+
+	local line =	b[4] + blshift(b[3], 8) + blshift(b[2], 16) + blshift(b[1], 24)
+	local col = 	b[8] + blshift(b[7], 8) + blshift(b[6], 16) + blshift(b[5], 24)
+	local type = 	b[10] + blshift(b[9], 8)
+	local len = 	b[12] + blshift(b[11], 8)
+	local raw =		nil
+
+	if len > 0 then raw = src:read(len) end
+	return { line = line, col = col, type = type, len = len, raw = raw }
+end
+
+-- This functions reads an asm line and tells if its a label or instructions
+-- If the return type is instructions, it will tell if its imm8, r8, etc
+--
+-- To keep the assembler simple we will only allow 0-3 operands. More is simply
+-- silly and unecessary for the goal.
+local ASM_UNKNOWN = 0
+local ASM_LABEL = 1
+local ASM_INSTRUCTION = 2
+local ASM_R8 = 3
+local ASM_IMM8 = 4
+
+local function operlyze(op, ret)
+	if isregs8(op) == true then
+		ret.opcount = 1
+		table.insert(ret.details, ASM_R8)
+	elseif op.type == tk_type.integer then
+		ret.opcount = 1
+		local val = intval(op.raw)
+
+		if val < 256 then
+			table.insert(ret.details, ASM_IMM8)
+		else
+			perror("operand 1 of instruction on line " .. op.line .. " is too big!")
+		end
+	elseif op.type == tk_type.hexadecimal then
+		ret.opcount = 1
+		local val = hexval(op.raw)
+
+		if val < 256 then
+			table.insert(ret.details, ASM_IMM8)
+		else
+			perror("operand 1 of instruction on line " .. op.line .. " is too big!")
+		end
+	elseif op.type == tk_type["\n"] then
+		ret.opcount = 0
+	else
+		perror("unknown operand `" .. gettokenkey(op) .. "` at line " .. op.line)
+	end
+end
+
+local function asmlyze(first)
+	if ismnemonic(first) == true then
+		local ret = { 
+			type = ASM_INSTRUCTION,
+			opcount = 0,
+			details = { }
+		}
+
+		local op1 = readhdr()
+		operlyze(op1, ret)
+
+		if ret.opcount == 0 then
+			return ret
+		end
+
+		local com = readhdr()
+
+		if com.type == tk_type["\n"] then
+			return ret
+		end
+
+		if com.type ~= tk_type[","] then
+			perror("missing comma next to first operand on line " .. op1.line)
+		end
+
+		local op2 = readhdr()
+		operlyze(op2, ret)
+
+		if ret.opcount == 0 then
+			return ret
+		end
+
+		com = readhdr()
+		if com.type == tk_type["\n"] then
+			return ret
+		end
+
+		if com.type ~= tk_type[","] then
+			perror("missing comma next to second operand on line " .. op1.line)
+		end
+
+		local op3 = readhdr()
+		operlyze(op3, ret)
+
+		if ret.opcount == 0 then
+			return ret
+		end
+
+		local nl = readhdr()
+		if nl.type == tk_type["\n"] then
+			return ret
+		end
+
+		perror("can only take up to 3 operands instructions. Line " .. first.line)
+
+	else
+		if first.type == tk_type.id then
+			local col = readhdr()
+			if col.type ~= tk_type[":"] then
+				perror("missing colon next to " .. gettokenkey(first) .. " line " .. first.line)
+			else
+				return { type = ASM_LABEL }
+			end
+			perror("Unknown instruction at line " .. first.line)
+		else
+			perror("illegal first element in instruction from line " .. first.line)
+		end
+	end
+end
+
+-----------------------------------------------------------------------
+-- 1st pass (syntax check and symbol table)
+-----------------------------------------------------------------------
+while true do
+	local hdr = readhdr()	
+	if hdr == nil then
+		break
+	end
+
+	if parser.inasm == true then
+		if hdr.type == tk_type["asm"] then
+			perror("illegal nested asm keyword at line " .. hdr.line .. " column " .. hdr.col)
+		elseif hdr.type == tk_type["}"] then
+			parser.inasm = false
+		else
+			if hdr.type ~= tk_type["\n"] then
+				local inst = asmlyze(hdr)
+
+				if inst.type == ASM_INSTRUCTION then
+					if hdr.type == tk_type["mov"] then
+						-- mov r8, r8
+						if inst.details[1] == ASM_R8 and inst.details[2] == ASM_R8 then
+							offset = offset + 2
+
+						-- mov r8, imm8
+						elseif inst.details[1] == ASM_R8 and inst.details[2] == ASM_IMM8 then
+							offset = offset + 2
+
+						-- huh?
+						else
+							perror("invalid instruction at line " .. hdr.line)
+						end
+					end
+				-- Add symbol table
+				elseif inst.type == ASM_LABEL then
+					symbol_table[hdr.raw] = offset
+				else
+					perror("Unknown instruction line " .. hdr.line)
+				end
+			end
+		end
+	else
+		if hdr.type == tk_type["asm"] then
+			local next = readhdr()
+			if next.type ~= tk_type["{"] then
+				perror("missing { after asm, line " .. hdr.line .. " column " .. hdr.col)
+			end
+			parser.inasm = true
+		end
+	end
+end
+
+-----------------------------------------------------------------------
+-- 2nd pass binary generation
+-----------------------------------------------------------------------
+
+-----------------------------------------------------------------------
+-- Closing files
+-----------------------------------------------------------------------
+src:close()
+dst:close()
blob - /dev/null
blob + cc7115c9a8b1920867e53e25cd21892a6d296e45 (mode 644)
--- /dev/null
+++ tools/util.lua
@@ -0,0 +1,221 @@
+-----------------------------------------------------------------------
+-- TOKEN MATCHING
+-----------------------------------------------------------------------
+local mnemonics = { "mov", "cli", "hlt", "ret", "sti" }
+
+local symbols = { ",", "[", "]", "(", ")", "{", "}", "*", "/", "-",
+	"+", "!", "~", "#", "?", ";", ":" }
+
+local regs8 = { "al", "ah", "bl", "bh", "cl", "ch", "dl", "dh" }
+
+local asmkwd = { "asm" }
+
+local tk_type = { }
+local count = 0
+
+for i = 1, #mnemonics do
+	count = count + 1
+	tk_type[mnemonics[i]] = count
+end
+
+for i = 1, #symbols do
+	count = count + 1
+	tk_type[symbols[i]] = count
+end
+
+for i = 1, #regs8 do
+	count = count + 1
+	tk_type[regs8[i]] = count
+end
+
+for i = 1, #asmkwd do
+	count = count + 1
+	tk_type[asmkwd[i]] = count
+end
+
+local function cincadd()
+	count = count + 1
+	return count
+end
+tk_type.hexadecimal = cincadd()
+tk_type.integer = cincadd()
+tk_type.id = cincadd()
+tk_type["\n"] = cincadd()
+
+-----------------------------------------------------------------------
+-- DEBUGING
+-----------------------------------------------------------------------
+local function perror(msg)
+	print(progname .. ": error: " .. msg)
+	os.exit(1)
+end
+
+-----------------------------------------------------------------------
+-- BOOLEAN check
+-----------------------------------------------------------------------
+local function isnumber(n)
+	if n:match("[0-9]") then
+		return true
+	end
+	return false
+end
+
+local function issymbol(char)
+	for i,v in ipairs(symbols) do
+		if v == char then
+			return true
+		end
+	end
+	return false
+end
+
+local function gettokenkey(m)
+	for i, v in pairs(tk_type) do
+		if tk_type[i] == m.type then
+			return i
+		end
+	end
+	return nil
+end
+
+local function ismnemonic(m)
+	local key = gettokenkey(m)
+
+	if key == nil then
+		return false
+	end
+
+	for i,v in ipairs(mnemonics) do
+		if v == key then
+			return true
+		end
+	end
+	return false
+end
+
+local function isregs8(m)
+	local key = gettokenkey(m)
+
+	if key == nil then
+		return false
+	end
+
+	for i,v in ipairs(regs8) do
+		if v == key then
+			return true
+		end
+	end
+	return false
+end
+
+-----------------------------------------------------------------------
+-- BITWISE OPERATIONS
+-----------------------------------------------------------------------
+local function brshift(value, bit)
+	return math.floor(value / (2 ^ bit))
+end
+
+local function blshift(value, bit)
+	return value * (2 ^ bit)
+end
+
+local function band(a, b)
+	local result = 0
+	local bitval = 1
+
+	while a > 0 and b > 0 do
+		if (a % 2 == 1) and (b % 2 == 1) then
+			result = result + bitval
+		end
+		a = math.floor(a / 2)
+		b = math.floor(b / 2)
+		bitval = bitval * 2
+	end
+
+	return result
+end
+
+local function bor(a, b)
+	local result = 0
+	local shift = 1
+
+	while a > 0 or b > 0 do
+		local r1 = a % 2
+		local r2 = b % 2
+
+		if r1 == 1 or r2 == 1 then
+			result = result + shift
+		end
+
+		a = math.floor(a / 2)
+		b = math.floor(b / 2)
+		shift = shift * 2
+	end
+
+	return result
+end
+
+-----------------------------------------------------------------------
+-- WRITE OPERATIONS
+-----------------------------------------------------------------------
+local function writeu8(dst, value)
+	local b = band(value, 0xff)
+	dst:write(string.char(b))
+end
+
+local function writeu16(dst, value)
+	local b2 = band(brshift(value, 8), 0xff)
+	local b1 = band(value, 0xff)
+
+	dst:write(string.char(b2, b1)) -- Little Endian x86
+end
+
+local function writeu32(dst, value)
+	local b4 = band(brshift(value, 24), 0xff)
+	local b3 = band(brshift(value, 16), 0xff)
+	local b2 = band(brshift(value, 8), 0xff)
+	local b1 = band(value, 0xff)
+
+	dst:write(string.char(b4, b3, b2, b1)) -- Little Endian x86
+end
+
+
+local function intval(intstr)
+	local len = #intstr
+	local res = 0
+
+	for i = 1, len do
+		local s = intstr:sub(len - i + 1, len - i + 1)
+		s = s * (10 ^ (i - 1))
+		res = res + s
+	end
+	return res
+end
+
+function hexval(hex)
+	local dig = hex:sub(3)
+	local len = #dig
+	local result = 0
+
+	for i = 1,len do
+		local d = dig:sub(i, i)
+
+		if d:lower() == "a" then
+			d = 10
+		elseif d:lower() == "b" then
+			d = 11
+		elseif d:lower() == "c" then
+			d = 12
+		elseif d:lower() == "d" then
+			d = 13
+		elseif d:lower() == "e" then
+			d = 14
+		elseif d:lower() == "f" then
+			d = 15
+		end
+
+		result = result + d * (16 ^ (len - i))
+	end
+
+	return result
+end