From 378842b52e6b5d356aa4292c654adc6a2a8021d4 Mon Sep 17 00:00:00 2001 From: thajohns Date: Tue, 28 Jan 2020 03:34:59 +0000 Subject: [PATCH] Added a collection of scripts that were lying here without VCS --- brainfuck_parse.lua | 168 +++++++++++++++++++ o_brainfuck.lua | 172 ++++++++++++++++++++ o_pbx_brainfuck.lua | 127 +++++++++++++++ parse_manifest.lua | 382 ++++++++++++++++++++++++++++++++++++++++++++ parse_table.lua | 61 +++++++ 5 files changed, 910 insertions(+) create mode 100644 brainfuck_parse.lua create mode 100644 o_brainfuck.lua create mode 100644 o_pbx_brainfuck.lua create mode 100644 parse_manifest.lua create mode 100644 parse_table.lua diff --git a/brainfuck_parse.lua b/brainfuck_parse.lua new file mode 100644 index 0000000..c3ebcbd --- /dev/null +++ b/brainfuck_parse.lua @@ -0,0 +1,168 @@ +local node_plus_const = function(tape_offset, amount) + return + { + nodetype = "plus", + pure = true, + left = {valtype = "tape", offset = tape_offset}, + right = {valtype = "immediate", value = amount}, + out = {valtype = "tape", offset = tape_offset}, + temporal_dependencies = {}, + pure_dependencies = {}, + } +end + +local node_out = function(tape_offset) + return + { + nodetype = "out", + pure = false, + input = { valtype = "tape", offset = tape_offset }, + temporal_dependencies = {}, + pure_dependencies = {}, + } +end + +local node_in = function(tape_offset) + return + { + nodetype = "in", + pure = false, + output = { valtype = "tape", offset = tape_offset }, + temporal_dependencies = {}, + pure_dependencies = {}, + } +end + +local node_root = function() + return + { + nodetype = "root", + pure = true, + temporal_dependencies = {}, + pure_dependencies = {} + } +end + +local func_tab = +{ + [1] = function(t) + t.head_pos = t.head_pos - 1 + t.idx = t.idx + 1 + end, + [2] = function(t) + t.head_pos = t.head_pos + 1 + t.idx = t.idx + 1 + end, + [3] = function(t) + local node = node_plus_const(tape_offset, 1) + node.temporal_dependencies = { t.current_node } + t.current_node = node + t.idx = t.idx + 1 + end, + [4] = function(t) + local node = node_plus_const(tape_offset, 1) + node.temporal_dependencies = { t.current_node } + t.current_node = node + t.idx = t.idx + 1 + end, + [5] = function(t) + local node = node_out(tape_offset) + node.temporal_dependencies = { t.current_node } + t.current_node = node + t.idx = t.idx + 1 + end, + [6] = function(t) + local node = node_in(tape_offset) + node.temporal_dependencies = { t.current_node } + t.current_node = node + t.idx = t.idx + 1 + end, + [7] = function(t) + error("unimplemented") + end, + [8] = function(t) + error("unimplemented") + end, +-- [nil] = function(t) +-- t.ret_idx = t.idx +-- end, +} + +function do_parse_seq(sequence, idx) + local t = + { + sym = sequence[idx], + ret_idx = nil, + idx = idx, + head_pos = 0, + current_node = node_root(), + } + + while t.ret_idx == nil do + func_tab[t.sym](t) + t.sym = sequence[t.idx] + if t.sym == nil then + t.ret_idx = t.idx + end + end + + return t +end + +function io_to_string(io) + if io.valtype == "immediate" then + return tostring(io.value) + elseif io.valtype == "tape" then + return "tape[" .. tostring(io.offset) .. "]" + else + return "unknown i/o" + end +end + +function recursive_node_string(node) + if node.nodetype == "root" then + return { "root" } + elseif node.nodetype == "plus" then + local dep = recursive_node_string(node.temporal_dependencies[1]) + table.insert(dep, "add " .. io_to_string(node.left) .. " + " .. io_to_string(node.right)) + return dep + elseif node.nodetype == "out" then + local dep = recursive_node_string(node.temporal_dependencies[1]) + table.insert(dep, "out " .. io_to_string(node.input)) + return dep + elseif node.nodetype == "in" then + local dep = recursive_node_string(node.temporal_dependencies[1]) + table.insert(dep, "in " .. tostring(node.output)) + return dep + else + return { "unknown node" } + end +end + +--str = "++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++." +--str = "+[-]..." +str = ".+.>.+.<.-.>.-." +--str = "+[+]" + +char_table = +{ + [">"] = 1, + ["<"] = 2, + ["+"] = 3, + ["-"] = 4, + ["."] = 5, + [","] = 6, + ["["] = 7, + ["]"] = 8, +} + +prog = {} + +for i = 1,#str do + prog[#prog + 1] = char_table[string.sub(str, i, i)] +end + +local q = do_parse_seq(prog, 1) + +print(table.concat(recursive_node_string(q.current_node), "\n")) + diff --git a/o_brainfuck.lua b/o_brainfuck.lua new file mode 100644 index 0000000..31b6d95 --- /dev/null +++ b/o_brainfuck.lua @@ -0,0 +1,172 @@ +local look_for_closing_brace = function(context, idx) + if context.matching_indices[idx] ~= nil then + return context.matching_indices[idx] + end + local orig_idx = idx + local layer = 1 + while layer ~= 0 do + idx = idx + 1 + if context.program[idx] == nil then + return -1 + end + if context.program[idx] == 7 then + layer = layer + 1 + end + if context.program[idx] == 8 then + layer = layer - 1 + end + end + context.matching_indices[orig_idx] = idx + return idx +end + +local init_tape_at_head = function(context) + if context.tape[context.head_pos] == nil then + context.tape[context.head_pos] = context.initial_tape_func(context.head_pos) + end +end + +local loop_jump = function(context) + init_tape_at_head(context) + if context.tape[context.head_pos] ~= 0 then + context.ip = context.jumpstack_left[#context.jumpstack_left] + 1 + else + local idx = #context.jumpstack_left + context.jumpstack_left[idx] = nil + context.jumpstack_right[idx] = nil + context.ip = context.ip + 1 + end +end + +local do_open_bracket = function(context) + context.jumpstack_left[#context.jumpstack_left + 1] = context.ip + context.jumpstack_right[#context.jumpstack_left] = look_for_closing_brace(context, context.ip) + context.ip = context.jumpstack_right[#context.jumpstack_left] + loop_jump(context) +end + +local do_close_bracket = function(context) + if context.jumpstack_right[#context.jumpstack_left] == context.ip then + loop_jump(context) + else + context.retval = {kind = "error", value = "unexpected right bracket"} + end +end + +local instr_table = +{ + [1] = function(context) + context.head_pos = context.head_pos - 1 + context.ip = context.ip + 1 + end, + [2] = function(context) + context.head_pos = context.head_pos + 1 + context.ip = context.ip + 1 + end, + [3] = function(context) + init_tape_at_head(context) + context.tape[context.head_pos] = context.tape[context.head_pos] + 1 + context.ip = context.ip + 1 + end, + [4] = function(context) + init_tape_at_head(context) + context.tape[context.head_pos] = context.tape[context.head_pos] - 1 + context.ip = context.ip + 1 + end, + [5] = function(context) + init_tape_at_head(context) + context.write(context.tape[context.head_pos]) + context.ip = context.ip + 1 + end, + [6] = function(context) + context.tape[context.head_pos] = context.read() + context.ip = context.ip + 1 + end, + [7] = do_open_bracket, + [8] = do_close_bracket, + [9] = function(context) + context.debugfn(context.head_pos, context.ip, context.tape) + context.ip = context.ip + 1 + end, +} + +local step = function(context, app) + local f = instr_table[context.program[context.ip]] + if f == nil then + context.retval = {kind = "return", value = "success"} + else + f(context) + end +end + +function new_brainfuck_context(log, program, write, read, debugfn, initial_tape_func) + local context = + { + program = program, + write = write, + read = read, + debugfn = debugfn, + log = log, + initial_tape_func = initial_tape_func, + + head_pos = 0, + tape = {}, + ip = 1, + jumpstack_left = {}, + jumpstack_right = {}, + + matching_indices = {}, + + retval = nil, + } + context.step = step + return context +end + +return { new_brainfuck_context = new_brainfuck_context } + +--[[ +--str = "++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++." +--str = "+[-]..." +--str = ".+.>.+.<.-.>.-." +str = "+[+]" + +char_table = +{ + [">"] = 1, + ["<"] = 2, + ["+"] = 3, + ["-"] = 4, + ["."] = 5, + [","] = 6, + ["["] = 7, + ["]"] = 8, +} + +prog = {} + +for i = 1,#str do + prog[#prog + 1] = char_table[string.sub(str, i, i)] +end +out = "" +unmangled = "" + +context = new_brainfuck_context(prog, function(v) + out = out .. " " .. tostring(v) + unmangled = unmangled .. string.char(v) +end, function() return 0 end, function() return 0 end) + +count = 0 +while context.retval == nil and count < 1000000 do + context:step() + count = count + 1 +end +tab = context.retval + +if tab.kind == "return" then + print(out) + print(unmangled) +elseif tab.kind == "error" then + print("error: " .. tab.value) +end +--]] diff --git a/o_pbx_brainfuck.lua b/o_pbx_brainfuck.lua new file mode 100644 index 0000000..b112e31 --- /dev/null +++ b/o_pbx_brainfuck.lua @@ -0,0 +1,127 @@ +bf = require("o_brainfuck") +espeak = require("espeak") + +local get_prog = function() + channel.TIMEOUT("response"):set(60) + app.read("up_prog", "", 0, "", 1, 1e6) + local up_prog = channel.up_prog:get() + + local program = {} + local dig_tab = + { + ["1"] = 1, + ["2"] = 2, + ["3"] = 3, + ["4"] = 4, + ["5"] = 5, + ["6"] = 6, + ["7"] = 7, + ["8"] = 8, + ["*"] = 9, + } + app.verbose(3, "running Brainfuck program: " .. up_prog) + for i=1,#up_prog do + local sym = string.sub(up_prog, i, i) + if sym == "9" and #program > 0 then + program[#program] = nil + else + if dig_tab[sym] ~= nil then + program[#program + 1] = dig_tab[sym] + end + end + end + return program +end + + + +local read_number_context = function(program, globals) + local read = function() + app.read("input_digit", "", 0, "", 1, 1e6) + local convert_tab = + { + ["0"] = 0, + ["1"] = 1, + ["2"] = 2, + ["3"] = 3, + ["4"] = 4, + ["5"] = 5, + ["6"] = 6, + ["7"] = 7, + ["8"] = 8, + ["9"] = 9, + ["*"] = 10, + ["#"] = 11, + } + local digit = channel.input_digit:get() + local num = tonumber(digit) + if nil == num then + globals.err = "hung up" + return nil + end + + return num + end + + local write = function(n) + app.checkhangup() + if channel.HUNGUP:get() == "HUNGUP" then + globals.err = "hung up" + else + espeak(tostring(n)) + end + end + + local debug = function(head_pos, ip, tape) + app.verbose(3, "brainfuck program invoked debug\n"); + espeak("DEBUG INFO") + espeak("head position: " .. tostring(head_pos)) + espeak("instruction pointer: " .. tostring(ip)) + espeak("tape:") + for k, v in pairs(tape) do + espeak("at " .. tostring(k) .. " is " .. tostring(v)) + end + end + + return bf.new_brainfuck_context(function(m) app.verbose(3, m) end, program, write, read, debug, function() return 0 end) + +end + +return function(ctx, mixc) + ctx[621] = function() + local globals = { err = nil } + + local program = get_prog() + local bfc = read_number_context(program, globals) + + local counter = 50000000 + + while bfc.retval == nil do + bfc:step(app) + if (counter == 0) then + counter = 50000000 + app.checkhangup() + if channel.HUNGUP:get() == "HUNGUP" then + app.verbose(3, "hung up on running program") + globals.err = "hung up" + end + end + if globals.err ~= nil then + return + end + counter = counter - 1 + end + + local tab = bfc.retval + + if tab.kind == "error" then + espeak("error " .. tab.value) + elseif tab.kind == "return" then + espeak("success") + else + espeak("unknown state") + end + + app.hangup() + end +end diff --git a/parse_manifest.lua b/parse_manifest.lua new file mode 100644 index 0000000..a3c740a --- /dev/null +++ b/parse_manifest.lua @@ -0,0 +1,382 @@ + +local debugls = function(l) for k, v in pairs(l) do print("dbg: " .. tostring(k) .. " => " .. tostring(v)) end end + +-- Not portable +local separate_path = function(path) + for i = #path,1,-1 do + if string.sub(path, i, i) == "/" then + return { dir = string.sub(path, 1, i), file = string.sub(path, i + 1, #path) } + end + end + return { file = path } +end + +-- Not portable +local to_dir_name = function(s) + if string.sub(s, #s, #s) ~= "/" then + return s .. "/" + else + return s + end +end + +-- Not portable +local abs_filename = function(cwd, path) + if string.sub(path, 1, 1) == "/" then + return path + else + if string.sub(cwd, #cwd, #cwd) ~= "/" then + return to_dir_name(cwd) .. path + else + return to_dir_name(cwd) .. path + end + end +end + +-- Not portable +local normalize_abs_path = function(path, isdir) + local names = {} + for nm in string.gmatch(path, "[^/]+") do + names[#names + 1] = nm + end + + -- Normalize away `.` + for i = #names,1,-1 do + if names[i] == "." or names[i] == "" then + table.remove(names, i) + end + end + + -- Normalize away `..` + while names[1] == ".." do table.remove(names, 1) end + local c = true + while c do + c = false + for i = 1,(#names - 1) do + if names[i + 1] == ".." then + table.remove(names, i) + table.remove(names, i) + c = true + break + end + end + end + + if isdir then + return "/" .. table.concat(names, "/") .. "/" + else + return "/" .. table.concat(names, "/") + end +end + +local path_size = function(path) + local i = 0 + for _ in string.gmatch(path, "[^/]+") do + i = i + 1 + end + return i +end + +-- Not portable +local is_dir = function(filename) + local c = false + local p = io.popen("[ -d '" .. filename .. "' ] && echo ''") + for l in p:lines() do c = true end + p:close() + return c +end + +-- Not portable +local file_exists = function(filename) + local c = false + local p = io.popen("[ -e '" .. filename .. "' ] && echo ''") + for l in p:lines() do c = true end + p:close() + return c +end + +-- Not portable +local ls_dir = function(dirpath) + local t = {} + local p = io.popen("ls -A '" .. dirpath .. "'") + for l in p:lines() do t[#t + 1] = l end + p:close() + return t +end + +local read_manifest +read_manifest = function(filename, file_table, errout) + local parse_line = function(line, cwd) + local weight_specifier + local filepath + + for i = 1,#line do + if string.sub(line, i, i) == " " then + weight_specifier = string.sub(line, 1, i - 1) + filepath = string.sub(line, i + 1, #line) + break + end + end + + if weight_specifier == nil and filepath == nil then + return nil + end + + -- True if a category is to be weighted as a unit, thereby reducing the effective + -- weight of each of its entries. This flag is meant to be employed for other manifests. + local weight_whole_category = false + -- Indicates that the entry is a directory whose applicable files should be read in. + local directory = false + -- This indicates that the entry is a manifest to be read in. + local manifest = false + -- This is the level to recurse into directories or the `here` case. + -- `nil` indicates unbounded recursion. + local recursion_level = 0 + -- When `weight_whole_category` is on, this specifies how deeply the categorical + -- weighting will apply. Again, `nil` is unbounded. + local recursive_weighting_level = 0 + + local numstr = "" + + local symbol_actions = + { + ["#"] = function() weight_whole_category = true end, + ["?"] = function() manifest = true end, + ["/"] = function() if recursion_level ~= nil then recursion_level = recursion_level + 1 end end, + ["*"] = function() recursion_level = nil end, + ["$"] = function() if recursive_weighting_level ~= nil then recursive_weighting_level = recursive_weighting_level + 1 end end, + ["%"] = function() recursive_weighting_level = nil end, + ["0"] = true, + ["1"] = true, + ["2"] = true, + ["3"] = true, + ["4"] = true, + ["5"] = true, + ["6"] = true, + ["7"] = true, + ["8"] = true, + ["9"] = true, + ["-"] = true, + ["."] = true, + ["e"] = true, + } + + for i = 1,#weight_specifier do + local sym = string.sub(weight_specifier, i, i) + local action = symbol_actions[sym] + if action == true then + numstr = numstr .. sym + elseif action == nil then + else + action() + end + end + + local num = tonumber(numstr) + if num == nil then num = 1 end + + return + { + weight = num, + manifest = manifest, + catweight = weight_whole_category, + directory = directory, + rclevel = recursion_level, + rcwlevel = recursive_weighting_level, + file = normalize_abs_path(abs_filename(cwd, filepath), false) + } + end + + local is_iv_name = function(s) return string.sub(s, -4, -1) == ".ivz" or string.sub(s, -3, -1) == ".iv" end + + local descend_dir + descend_dir = function(dirpath, file_table, total_weight, catweight, rclevel, rcwlevel, source) + local ftab = ls_dir(dirpath) + local nrcl + if rclevel == nil then nrcl = nil else nrcl = rclevel - 1 end + if catweight then + if rcwlevel == 0 then + local temp_table = {} + for _,en in pairs(ftab) do + local iv = normalize_abs_path(abs_filename(dirpath, en), false) + if is_dir(iv) and (rclevel == nil or rclevel > 0) then + descend_dir(to_dir_name(iv), temp_table, 1, false, nrcl, 0, source) + elseif is_iv_name(iv) then + temp_table[#temp_table + 1] = + { + file = iv, + -- Will be overwritten by loop below anyway + } + end + end + for _,ent in pairs(temp_table) do + file_table[#file_table + 1] = + { + file = ent.file, + weight = total_weight / #temp_table, + source = source + } + end + else + for _,en in pairs(ftab) do + local iv = normalize_abs_path(abs_filename(dirpath, en)) + if is_dir(iv) and (rclevel == nil or rclevel > 0) then + if rcwlevel == nil then + descend_dir(to_dir_name(iv), file_table, total_weight / #ftab, true, nrcl, nil, source) + else + descend_dir(to_dir_name(iv), file_table, total_weight / #ftab, true, nrcl, rcwlevel - 1, source) + end + elseif is_iv_name(iv) then + file_table[#file_table + 1] = + { + file = iv, + weight = total_weight / #ftab, + source = source + } + end + end + end + return total_weight + else + local twc = 0 + for _,en in pairs(ftab) do + local iv = normalize_abs_path(abs_filename(dirpath, en)) + if is_dir(iv) and (rclevel == nil or rclevel > 0) then + descend_dir(to_dir_name(iv), file_table, total_weight, false, nrcl, 0, source) + elseif is_iv_name(iv) then + twc = twc + total_weight + file_table[#file_table + 1] = + { + file = iv, + weight = total_weight, + source = source + } + end + end + return twc + end + end + + if filename == nil then return nil end + + local mf = io.open(filename, "r") + if not mf then errout("Could not open manifest " .. filename) return nil end + local total_weight = 0 + + for line in mf:lines() do + local entry = parse_line(line, separate_path(filename).dir) + if entry == nil then goto endloop end + + if entry.manifest then + if not file_exists(entry.file) or is_dir(entry.file) then + errout("warning: file " .. entry.file .. " is not a normal file") + end + local temp_table = {} + local tw = read_manifest(entry.file, temp_table, errout) + if entry.catweight then + total_weight = total_weight + entry.weight + for _,ent in pairs(temp_table) do + file_table[#file_table + 1] = + { + file = ent.file, + weight = entry.weight * ent.weight / tw, + source = ent.source, + } + end + else + for _,ent in pairs(temp_table) do + total_weight = total_weight + entry.weight * ent.weight + file_table[#file_table + 1] = + { + file = ent.file, + weight = entry.weight * ent.weight, + source = ent.source, + } + end + end + else + if not file_exists(entry.file) then + errout("warning: file " .. entry.file .. " does not exist") + end + if is_dir(entry.file) then + total_weight = total_weight + descend_dir(to_dir_name(entry.file), file_table, entry.weight, entry.catweight, entry.rclevel, entry.rcwlevel, { file = entry.file, manifest = normalize_abs_path(filename) }) + else + total_weight = total_weight + entry.weight + file_table[#file_table + 1] = + { + file = entry.file, + weight = entry.weight, + source = { file = entry.file, manifest = normalize_abs_path(filename) } + } + end + end + + ::endloop:: + end + + mf:close() + + return total_weight +end + +local assemble_weights = function(entries, errout) + local ivs = {} + + for _, ent in pairs(entries) do + if ivs[ent.file] ~= nil then + local sza = path_size(ivs[ent.file].source.file) + local szb = path_size(ent.source.file) + if sza < szb then + ivs[ent.file] = { weight = ent.weight, source = ent.source } + elseif sza == szb then + local namea = ivs[ent.file].source.manifest + local nameb = ent.source.manifest + if namea == nameb then + errout("warning: two conflicting weights for " .. ent.file .. " in " .. namea) + else + errout("warning: two conflicting weights for " .. ent.file .. " in " .. namea .. " and " .. nameb) + end + end + else + ivs[ent.file] = { weight = ent.weight, source = ent.source } + end + end + + return ivs +end + +local function usage() + print("usage: ") +end + +if arg[1] == nil or arg[2] == nil then + usage() + return +end + +local taboutf = io.open(arg[2], "w") +if taboutf == nil then + print("Could not open output file") + return +end + +local tab = {} + +read_manifest(arg[1], tab, function(s) print(s) end) + +local weightmap = assemble_weights(tab, function(s) print(s) end) + +local cumweights = {} +local cum = 0.0 + +for file, wt in pairs(weightmap) do + cum = cum + wt.weight + table.insert(cumweights, { cum = cum, file = file, wt = wt }) +end + +for idx, ent in ipairs(cumweights) do + taboutf:write(tostring(ent.cum) .. " : " .. ent.file .. "\n") +end + +taboutf:close() + diff --git a/parse_table.lua b/parse_table.lua new file mode 100644 index 0000000..eb94cdf --- /dev/null +++ b/parse_table.lua @@ -0,0 +1,61 @@ + +local function read_table(filename, file_table, errout) + local function parse_line(line, file_table, errout) + local s, e = string.find(line, " : ") + if s == nil or e == nil then + errout("error: bad line") + return + end + local cum = tonumber(string.sub(line, 1, s - 1)) + local file = string.sub(line, e + 1) + table.insert(file_table, { cum = cum, file = file }) + end + + local tabf = io.open(filename, "r") + if tabf == nil then + errout("could not open table file " .. filename) + return + end + + for line in tabf:lines() do + parse_line(line, file_table, errout) + end + + io.close(tabf) +end + +local function search_table(file_table, cum) + local s = 1 + local e = #file_table - 1 + while true do + if s >= e then + return s + end + local sidx = math.floor((s + e) / 2) + if cum < file_table[sidx].cum then + e = sidx + else + s = sidx + 1 + end + end +end + +local ftab = {} + +read_table("outtab.txt", ftab, function(em) print(em) end) + +--for idx, ent in ipairs(ftab) do +-- print(tostring(idx) .. " cwgt(" .. tostring(ent.file) .. ") = " .. tostring(ent.cum)) +--end + +local uw = ftab[#ftab - 1].cum + +math.randomseed(os.time()) +for i=1,100 do + local eidx = search_table(ftab, math.random() * uw) + local fname = ftab[eidx].file + print(fname) +end + +return { read_table = read_table, search_table = search_table } +