Browse Source

Added a collection of scripts that were lying here without VCS

Thomas Johnson 1 year ago
commit
378842b52e
5 changed files with 910 additions and 0 deletions
  1. 168
    0
      brainfuck_parse.lua
  2. 172
    0
      o_brainfuck.lua
  3. 127
    0
      o_pbx_brainfuck.lua
  4. 382
    0
      parse_manifest.lua
  5. 61
    0
      parse_table.lua

+ 168
- 0
brainfuck_parse.lua View File

@@ -0,0 +1,168 @@
1
+local node_plus_const = function(tape_offset, amount)
2
+	return
3
+	{
4
+		nodetype = "plus",
5
+		pure = true,
6
+		left = {valtype = "tape", offset = tape_offset},
7
+		right = {valtype = "immediate", value = amount},
8
+		out = {valtype = "tape", offset = tape_offset},
9
+		temporal_dependencies = {},
10
+		pure_dependencies = {},
11
+	}
12
+end
13
+
14
+local node_out = function(tape_offset)
15
+	return
16
+	{
17
+		nodetype = "out",
18
+		pure = false,
19
+		input = { valtype = "tape", offset = tape_offset },
20
+		temporal_dependencies = {},
21
+		pure_dependencies = {},
22
+	}
23
+end
24
+
25
+local node_in = function(tape_offset)
26
+	return
27
+	{
28
+		nodetype = "in",
29
+		pure = false,
30
+		output = { valtype = "tape", offset = tape_offset },
31
+		temporal_dependencies = {},
32
+		pure_dependencies = {},
33
+	}
34
+end
35
+
36
+local node_root = function()
37
+	return 
38
+	{
39
+		nodetype = "root",
40
+		pure = true,
41
+		temporal_dependencies = {},
42
+		pure_dependencies = {}
43
+	}
44
+end
45
+
46
+local func_tab =
47
+{
48
+	[1] = function(t)
49
+		t.head_pos = t.head_pos - 1
50
+		t.idx = t.idx + 1
51
+	end,
52
+	[2] = function(t)
53
+		t.head_pos = t.head_pos + 1
54
+		t.idx = t.idx + 1
55
+	end,
56
+	[3] = function(t)
57
+		local node = node_plus_const(tape_offset, 1)
58
+		node.temporal_dependencies = { t.current_node }
59
+		t.current_node = node
60
+		t.idx = t.idx + 1
61
+	end,
62
+	[4] = function(t)
63
+		local node = node_plus_const(tape_offset, 1)
64
+		node.temporal_dependencies = { t.current_node }
65
+		t.current_node = node
66
+		t.idx = t.idx + 1
67
+	end,
68
+	[5] = function(t)
69
+		local node = node_out(tape_offset)
70
+		node.temporal_dependencies = { t.current_node }
71
+		t.current_node = node
72
+		t.idx = t.idx + 1
73
+	end,
74
+	[6] = function(t)
75
+		local node = node_in(tape_offset)
76
+		node.temporal_dependencies = { t.current_node }
77
+		t.current_node = node
78
+		t.idx = t.idx + 1
79
+	end,
80
+	[7] = function(t)
81
+		error("unimplemented")
82
+	end,
83
+	[8] = function(t)
84
+		error("unimplemented")
85
+	end,
86
+--	[nil] = function(t)
87
+--		t.ret_idx = t.idx
88
+--	end,
89
+}
90
+
91
+function do_parse_seq(sequence, idx)
92
+	local t =
93
+	{
94
+		sym = sequence[idx],
95
+		ret_idx = nil,
96
+		idx = idx,
97
+		head_pos = 0,
98
+		current_node = node_root(),
99
+	}
100
+
101
+	while t.ret_idx == nil do
102
+		func_tab[t.sym](t)
103
+		t.sym = sequence[t.idx]
104
+		if t.sym == nil then
105
+			t.ret_idx = t.idx
106
+		end
107
+	end
108
+
109
+	return t
110
+end
111
+
112
+function io_to_string(io)
113
+	if io.valtype == "immediate" then
114
+		return tostring(io.value)
115
+	elseif io.valtype == "tape" then
116
+		return "tape[" .. tostring(io.offset) .. "]"
117
+	else
118
+		return "unknown i/o"
119
+	end
120
+end
121
+
122
+function recursive_node_string(node)
123
+	if node.nodetype == "root" then
124
+		return { "root" }
125
+	elseif node.nodetype == "plus" then
126
+		local dep = recursive_node_string(node.temporal_dependencies[1])
127
+		table.insert(dep, "add " .. io_to_string(node.left) .. " + " .. io_to_string(node.right))
128
+		return dep
129
+	elseif node.nodetype == "out" then
130
+		local dep = recursive_node_string(node.temporal_dependencies[1])
131
+		table.insert(dep, "out " .. io_to_string(node.input))
132
+		return dep
133
+	elseif node.nodetype == "in" then
134
+		local dep = recursive_node_string(node.temporal_dependencies[1])
135
+		table.insert(dep, "in " .. tostring(node.output))
136
+		return dep
137
+	else
138
+		return { "unknown node" }
139
+	end
140
+end
141
+
142
+--str = "++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++."
143
+--str = "+[-]..."
144
+str = ".+.>.+.<.-.>.-."
145
+--str = "+[+]"
146
+
147
+char_table = 
148
+{
149
+	[">"] = 1,
150
+	["<"] = 2,
151
+	["+"] = 3,
152
+	["-"] = 4,
153
+	["."] = 5,
154
+	[","] = 6,
155
+	["["] = 7,
156
+	["]"] = 8,
157
+}
158
+
159
+prog = {}
160
+
161
+for i = 1,#str do
162
+	prog[#prog + 1] = char_table[string.sub(str, i, i)]
163
+end
164
+
165
+local q = do_parse_seq(prog, 1)
166
+
167
+print(table.concat(recursive_node_string(q.current_node), "\n"))
168
+

+ 172
- 0
o_brainfuck.lua View File

@@ -0,0 +1,172 @@
1
+local look_for_closing_brace = function(context, idx)
2
+	if context.matching_indices[idx] ~= nil then
3
+		return context.matching_indices[idx]
4
+	end
5
+	local orig_idx = idx
6
+	local layer = 1
7
+	while layer ~= 0 do
8
+		idx = idx + 1
9
+		if context.program[idx] == nil then
10
+			return -1
11
+		end
12
+		if context.program[idx] == 7 then
13
+			layer = layer + 1
14
+		end
15
+		if context.program[idx] == 8 then
16
+			layer = layer - 1
17
+		end
18
+	end
19
+	context.matching_indices[orig_idx] = idx
20
+	return idx
21
+end
22
+
23
+local init_tape_at_head = function(context)
24
+	if context.tape[context.head_pos] == nil then
25
+		context.tape[context.head_pos] = context.initial_tape_func(context.head_pos)
26
+	end
27
+end
28
+
29
+local loop_jump = function(context)
30
+	init_tape_at_head(context)
31
+	if context.tape[context.head_pos] ~= 0 then
32
+		context.ip = context.jumpstack_left[#context.jumpstack_left] + 1
33
+	else
34
+		local idx = #context.jumpstack_left
35
+		context.jumpstack_left[idx] = nil
36
+		context.jumpstack_right[idx] = nil
37
+		context.ip = context.ip + 1
38
+	end
39
+end
40
+
41
+local do_open_bracket = function(context)
42
+	context.jumpstack_left[#context.jumpstack_left + 1] = context.ip
43
+	context.jumpstack_right[#context.jumpstack_left] = look_for_closing_brace(context, context.ip)
44
+	context.ip = context.jumpstack_right[#context.jumpstack_left]
45
+	loop_jump(context)
46
+end
47
+
48
+local do_close_bracket = function(context)
49
+	if context.jumpstack_right[#context.jumpstack_left] == context.ip then
50
+		loop_jump(context)
51
+	else
52
+		context.retval = {kind = "error", value = "unexpected right bracket"}
53
+	end
54
+end
55
+
56
+local instr_table = 
57
+{
58
+	[1] = function(context)
59
+		context.head_pos = context.head_pos - 1
60
+		context.ip = context.ip + 1
61
+	end,
62
+	[2] = function(context)
63
+		context.head_pos = context.head_pos + 1
64
+		context.ip = context.ip + 1
65
+	end,
66
+	[3] = function(context)
67
+		init_tape_at_head(context)
68
+		context.tape[context.head_pos] = context.tape[context.head_pos] + 1
69
+		context.ip = context.ip + 1
70
+	end,
71
+	[4] = function(context)
72
+		init_tape_at_head(context)
73
+		context.tape[context.head_pos] = context.tape[context.head_pos] - 1
74
+		context.ip = context.ip + 1
75
+	end,
76
+	[5] = function(context)
77
+		init_tape_at_head(context)
78
+		context.write(context.tape[context.head_pos])
79
+		context.ip = context.ip + 1
80
+	end,
81
+	[6] = function(context)
82
+		context.tape[context.head_pos] = context.read()
83
+		context.ip = context.ip + 1
84
+	end,
85
+	[7] = do_open_bracket,
86
+	[8] = do_close_bracket,
87
+	[9] = function(context)
88
+		context.debugfn(context.head_pos, context.ip, context.tape)
89
+		context.ip = context.ip + 1
90
+	end,
91
+}
92
+
93
+local step = function(context, app)
94
+	local f = instr_table[context.program[context.ip]]
95
+	if f == nil then
96
+		context.retval = {kind = "return", value = "success"}
97
+	else
98
+		f(context)
99
+	end
100
+end
101
+
102
+function new_brainfuck_context(log, program, write, read, debugfn, initial_tape_func)
103
+	local context =
104
+	{
105
+		program = program,
106
+		write = write,
107
+		read = read,
108
+		debugfn = debugfn,
109
+		log = log,
110
+		initial_tape_func = initial_tape_func,
111
+
112
+		head_pos = 0,
113
+		tape = {},
114
+		ip = 1,
115
+		jumpstack_left = {},
116
+		jumpstack_right = {},
117
+
118
+		matching_indices = {},
119
+
120
+		retval = nil,
121
+	}
122
+	context.step = step
123
+	return context
124
+end
125
+
126
+return { new_brainfuck_context = new_brainfuck_context }
127
+
128
+--[[
129
+--str = "++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++."
130
+--str = "+[-]..."
131
+--str = ".+.>.+.<.-.>.-."
132
+str = "+[+]"
133
+
134
+char_table = 
135
+{
136
+	[">"] = 1,
137
+	["<"] = 2,
138
+	["+"] = 3,
139
+	["-"] = 4,
140
+	["."] = 5,
141
+	[","] = 6,
142
+	["["] = 7,
143
+	["]"] = 8,
144
+}
145
+
146
+prog = {}
147
+
148
+for i = 1,#str do
149
+	prog[#prog + 1] = char_table[string.sub(str, i, i)]
150
+end
151
+out = ""
152
+unmangled = ""
153
+
154
+context = new_brainfuck_context(prog, function(v)
155
+	out = out .. " " .. tostring(v)
156
+	unmangled = unmangled .. string.char(v)
157
+end, function() return 0 end, function() return 0 end)
158
+
159
+count = 0
160
+while context.retval == nil and count < 1000000 do
161
+	context:step()
162
+	count = count + 1
163
+end
164
+tab = context.retval
165
+
166
+if tab.kind == "return" then
167
+	print(out)
168
+	print(unmangled)
169
+elseif tab.kind == "error" then
170
+	print("error: " .. tab.value)
171
+end
172
+--]]

+ 127
- 0
o_pbx_brainfuck.lua View File

@@ -0,0 +1,127 @@
1
+bf = require("o_brainfuck")
2
+espeak = require("espeak")
3
+
4
+local get_prog = function()
5
+	channel.TIMEOUT("response"):set(60)
6
+	app.read("up_prog", "", 0, "", 1, 1e6)
7
+	local up_prog = channel.up_prog:get()
8
+
9
+	local program = {}
10
+	local dig_tab =
11
+	{
12
+		["1"] = 1,
13
+		["2"] = 2,
14
+		["3"] = 3,
15
+		["4"] = 4,
16
+		["5"] = 5,
17
+		["6"] = 6,
18
+		["7"] = 7,
19
+		["8"] = 8,
20
+		["*"] = 9,
21
+	}
22
+	app.verbose(3, "running Brainfuck program: " .. up_prog)
23
+	for i=1,#up_prog do
24
+		local sym = string.sub(up_prog, i, i)
25
+		if sym == "9" and #program > 0 then
26
+			program[#program] = nil
27
+		else
28
+			if dig_tab[sym] ~= nil then
29
+				program[#program + 1] = dig_tab[sym]
30
+			end
31
+		end
32
+	end
33
+	return program
34
+end
35
+
36
+
37
+
38
+local read_number_context = function(program, globals)
39
+	local read = function()
40
+		app.read("input_digit", "", 0, "", 1, 1e6)
41
+		local convert_tab =
42
+		{
43
+			["0"] = 0,
44
+			["1"] = 1,
45
+			["2"] = 2,
46
+			["3"] = 3,
47
+			["4"] = 4,
48
+			["5"] = 5,
49
+			["6"] = 6,
50
+			["7"] = 7,
51
+			["8"] = 8,
52
+			["9"] = 9,
53
+			["*"] = 10,
54
+			["#"] = 11,
55
+		}
56
+		local digit = channel.input_digit:get()
57
+		local num = tonumber(digit)
58
+		if nil == num then
59
+			globals.err = "hung up"
60
+			return nil
61
+		end
62
+
63
+		return num
64
+	end
65
+
66
+	local write = function(n)
67
+		app.checkhangup()
68
+		if channel.HUNGUP:get() == "HUNGUP" then
69
+			globals.err = "hung up"
70
+		else
71
+			espeak(tostring(n))
72
+		end
73
+	end
74
+
75
+	local debug = function(head_pos, ip, tape)
76
+		app.verbose(3, "brainfuck program invoked debug\n");
77
+		espeak("DEBUG INFO")
78
+		espeak("head position: " .. tostring(head_pos))
79
+		espeak("instruction pointer: " .. tostring(ip))
80
+		espeak("tape:")
81
+		for k, v in pairs(tape) do
82
+			espeak("at " .. tostring(k) .. " is " .. tostring(v))
83
+		end
84
+	end
85
+
86
+	return bf.new_brainfuck_context(function(m) app.verbose(3, m) end, program, write, read, debug, function() return 0 end)
87
+
88
+end
89
+
90
+return function(ctx, mixc)
91
+	ctx[621] = function()
92
+		local globals = { err = nil }
93
+
94
+		local program = get_prog()
95
+		local bfc = read_number_context(program, globals)
96
+
97
+		local counter = 50000000
98
+
99
+		while bfc.retval == nil do
100
+			bfc:step(app)
101
+			if (counter == 0) then
102
+				counter = 50000000
103
+				app.checkhangup()
104
+				if channel.HUNGUP:get() == "HUNGUP" then
105
+					app.verbose(3, "hung up on running program")
106
+					globals.err = "hung up"
107
+				end
108
+			end
109
+			if globals.err ~= nil then
110
+				return
111
+			end
112
+			counter = counter - 1
113
+		end
114
+
115
+		local tab = bfc.retval
116
+
117
+		if tab.kind == "error" then
118
+			espeak("error " .. tab.value)
119
+		elseif tab.kind == "return" then
120
+			espeak("success")
121
+		else
122
+			espeak("unknown state")
123
+		end
124
+
125
+		app.hangup()
126
+	end
127
+end

+ 382
- 0
parse_manifest.lua View File

@@ -0,0 +1,382 @@
1
+
2
+local debugls = function(l) for k, v in pairs(l) do print("dbg: " .. tostring(k) .. " => " .. tostring(v)) end end
3
+
4
+-- Not portable
5
+local separate_path = function(path)
6
+	for i = #path,1,-1 do
7
+		if string.sub(path, i, i) == "/" then
8
+			return { dir = string.sub(path, 1, i), file = string.sub(path, i + 1, #path) }
9
+		end
10
+	end
11
+	return { file = path }
12
+end
13
+
14
+-- Not portable
15
+local to_dir_name = function(s)
16
+	if string.sub(s, #s, #s) ~= "/" then
17
+		return s .. "/"
18
+	else
19
+		return s
20
+	end
21
+end
22
+
23
+-- Not portable
24
+local abs_filename = function(cwd, path)
25
+	if string.sub(path, 1, 1) == "/" then
26
+		return path
27
+	else
28
+		if string.sub(cwd, #cwd, #cwd) ~= "/" then
29
+			return to_dir_name(cwd) .. path
30
+		else
31
+			return to_dir_name(cwd) .. path
32
+		end
33
+	end
34
+end
35
+
36
+-- Not portable
37
+local normalize_abs_path = function(path, isdir)
38
+	local names = {}
39
+	for nm in string.gmatch(path, "[^/]+") do
40
+		names[#names + 1] = nm
41
+	end
42
+
43
+	-- Normalize away `.`
44
+	for i = #names,1,-1 do
45
+		if names[i] == "." or names[i] == "" then
46
+			table.remove(names, i)
47
+		end
48
+	end
49
+
50
+	-- Normalize away `..`
51
+	while names[1] == ".." do table.remove(names, 1) end
52
+	local c = true
53
+	while c do
54
+		c = false
55
+		for i = 1,(#names - 1) do
56
+			if names[i + 1] == ".." then
57
+				table.remove(names, i)
58
+				table.remove(names, i)
59
+				c = true
60
+				break
61
+			end
62
+		end
63
+	end
64
+
65
+	if isdir then
66
+		return "/" .. table.concat(names, "/") .. "/"
67
+	else
68
+		return "/" .. table.concat(names, "/")
69
+	end
70
+end
71
+
72
+local path_size = function(path)
73
+	local i = 0
74
+	for _ in string.gmatch(path, "[^/]+") do
75
+		i = i + 1
76
+	end
77
+	return i
78
+end
79
+
80
+-- Not portable
81
+local is_dir = function(filename)
82
+	local c = false
83
+	local p = io.popen("[ -d '" .. filename .. "' ] && echo ''")
84
+	for l in p:lines() do c = true end
85
+	p:close()
86
+	return c
87
+end
88
+
89
+-- Not portable
90
+local file_exists = function(filename)
91
+	local c = false
92
+	local p = io.popen("[ -e '" .. filename .. "' ] && echo ''")
93
+	for l in p:lines() do c = true end
94
+	p:close()
95
+	return c
96
+end
97
+
98
+-- Not portable
99
+local ls_dir = function(dirpath)
100
+	local t = {}
101
+	local p = io.popen("ls -A '" .. dirpath .. "'")
102
+	for l in p:lines() do t[#t + 1] = l end
103
+	p:close()
104
+	return t
105
+end
106
+
107
+local read_manifest
108
+read_manifest = function(filename, file_table, errout)
109
+	local parse_line = function(line, cwd)
110
+		local weight_specifier
111
+		local filepath
112
+
113
+		for i = 1,#line do
114
+			if string.sub(line, i, i) == " " then
115
+				weight_specifier = string.sub(line, 1, i - 1)
116
+				filepath = string.sub(line, i + 1, #line)
117
+				break
118
+			end
119
+		end
120
+		
121
+		if weight_specifier == nil and filepath == nil then
122
+			return nil
123
+		end
124
+
125
+		-- True if a category is to be weighted as a unit, thereby reducing the effective
126
+		-- weight of each of its entries. This flag is meant to be employed for other manifests.
127
+		local weight_whole_category = false
128
+		-- Indicates that the entry is a directory whose applicable files should be read in.
129
+		local directory = false
130
+		-- This indicates that the entry is a manifest to be read in.
131
+		local manifest = false
132
+		-- This is the level to recurse into directories or the `here` case.
133
+		-- `nil` indicates unbounded recursion.
134
+		local recursion_level = 0
135
+		-- When `weight_whole_category` is on, this specifies how deeply the categorical
136
+		-- weighting will apply. Again, `nil` is unbounded.
137
+		local recursive_weighting_level = 0
138
+
139
+		local numstr = ""
140
+
141
+		local symbol_actions = 
142
+		{
143
+			["#"] = function() weight_whole_category = true end,
144
+			["?"] = function() manifest = true end,
145
+			["/"] = function() if recursion_level ~= nil then recursion_level = recursion_level + 1 end end,
146
+			["*"] = function() recursion_level = nil end,
147
+			["$"] = function() if recursive_weighting_level ~= nil then recursive_weighting_level = recursive_weighting_level + 1 end end,
148
+			["%"] = function() recursive_weighting_level = nil end,
149
+			["0"] = true,
150
+			["1"] = true,
151
+			["2"] = true,
152
+			["3"] = true,
153
+			["4"] = true,
154
+			["5"] = true,
155
+			["6"] = true,
156
+			["7"] = true,
157
+			["8"] = true,
158
+			["9"] = true,
159
+			["-"] = true,
160
+			["."] = true,
161
+			["e"] = true,
162
+		}
163
+
164
+		for i = 1,#weight_specifier do
165
+			local sym = string.sub(weight_specifier, i, i)
166
+			local action = symbol_actions[sym]
167
+			if action == true then
168
+				numstr = numstr .. sym
169
+			elseif action == nil then
170
+			else
171
+				action()
172
+			end
173
+		end
174
+
175
+		local num = tonumber(numstr)
176
+		if num == nil then num = 1 end
177
+
178
+		return
179
+		{
180
+			weight = num,
181
+			manifest = manifest,
182
+			catweight = weight_whole_category,
183
+			directory = directory,
184
+			rclevel = recursion_level,
185
+			rcwlevel = recursive_weighting_level,
186
+			file = normalize_abs_path(abs_filename(cwd, filepath), false)
187
+		}
188
+	end
189
+
190
+	local is_iv_name = function(s) return string.sub(s, -4, -1) == ".ivz" or string.sub(s, -3, -1) == ".iv" end
191
+
192
+	local descend_dir
193
+	descend_dir = function(dirpath, file_table, total_weight, catweight, rclevel, rcwlevel, source)
194
+		local ftab = ls_dir(dirpath)
195
+		local nrcl
196
+		if rclevel == nil then nrcl = nil else nrcl = rclevel - 1 end
197
+		if catweight then
198
+			if rcwlevel == 0 then
199
+				local temp_table = {}
200
+				for _,en in pairs(ftab) do
201
+					local iv = normalize_abs_path(abs_filename(dirpath, en), false)
202
+					if is_dir(iv) and (rclevel == nil or rclevel > 0) then
203
+						descend_dir(to_dir_name(iv), temp_table, 1, false, nrcl, 0, source)
204
+					elseif is_iv_name(iv) then
205
+						temp_table[#temp_table + 1] =
206
+						{
207
+							file = iv,
208
+							-- Will be overwritten by loop below anyway
209
+						}
210
+					end
211
+				end
212
+				for _,ent in pairs(temp_table) do
213
+					file_table[#file_table + 1] =
214
+					{
215
+						file = ent.file,
216
+						weight = total_weight / #temp_table,
217
+						source = source
218
+					}
219
+				end
220
+			else
221
+				for _,en in pairs(ftab) do
222
+					local iv = normalize_abs_path(abs_filename(dirpath, en))
223
+					if is_dir(iv) and (rclevel == nil or rclevel > 0) then
224
+						if rcwlevel == nil then
225
+							descend_dir(to_dir_name(iv), file_table, total_weight / #ftab, true, nrcl, nil, source)
226
+						else
227
+							descend_dir(to_dir_name(iv), file_table, total_weight / #ftab, true, nrcl, rcwlevel - 1, source)
228
+						end
229
+					elseif is_iv_name(iv) then
230
+						file_table[#file_table + 1] =
231
+						{
232
+							file = iv,
233
+							weight = total_weight / #ftab,
234
+							source = source
235
+						}
236
+					end
237
+				end
238
+			end
239
+			return total_weight
240
+		else
241
+			local twc = 0
242
+			for _,en in pairs(ftab) do
243
+				local iv = normalize_abs_path(abs_filename(dirpath, en))
244
+				if is_dir(iv) and (rclevel == nil or rclevel > 0) then
245
+					descend_dir(to_dir_name(iv), file_table, total_weight, false, nrcl, 0, source)
246
+				elseif is_iv_name(iv) then
247
+					twc = twc + total_weight
248
+					file_table[#file_table + 1] =
249
+					{
250
+						file = iv,
251
+						weight = total_weight,
252
+						source = source
253
+					}
254
+				end
255
+			end
256
+			return twc
257
+		end
258
+	end
259
+
260
+	if filename == nil then return nil end
261
+
262
+	local mf = io.open(filename, "r")
263
+	if not mf then errout("Could not open manifest " .. filename) return nil end
264
+	local total_weight = 0
265
+
266
+	for line in mf:lines() do
267
+		local entry = parse_line(line, separate_path(filename).dir)
268
+		if entry == nil then goto endloop end
269
+
270
+		if entry.manifest then
271
+			if not file_exists(entry.file) or is_dir(entry.file) then
272
+				errout("warning: file " .. entry.file .. " is not a normal file")
273
+			end
274
+			local temp_table = {}
275
+			local tw = read_manifest(entry.file, temp_table, errout)
276
+			if entry.catweight then
277
+				total_weight = total_weight + entry.weight
278
+				for _,ent in pairs(temp_table) do
279
+					file_table[#file_table + 1] =
280
+					{
281
+						file = ent.file,
282
+						weight = entry.weight * ent.weight / tw,
283
+						source = ent.source,
284
+					}
285
+				end
286
+			else
287
+				for _,ent in pairs(temp_table) do
288
+					total_weight = total_weight + entry.weight * ent.weight
289
+					file_table[#file_table + 1] =
290
+					{
291
+						file = ent.file,
292
+						weight = entry.weight * ent.weight,
293
+						source = ent.source,
294
+					}
295
+				end
296
+			end
297
+		else
298
+			if not file_exists(entry.file) then
299
+				errout("warning: file " .. entry.file .. " does not exist")
300
+			end
301
+			if is_dir(entry.file) then
302
+				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) })
303
+			else
304
+				total_weight = total_weight + entry.weight
305
+				file_table[#file_table + 1] =
306
+				{
307
+					file = entry.file,
308
+					weight = entry.weight,
309
+					source = { file = entry.file, manifest = normalize_abs_path(filename) }
310
+				}
311
+			end
312
+		end
313
+
314
+		::endloop::
315
+	end
316
+
317
+	mf:close()
318
+
319
+	return total_weight
320
+end
321
+
322
+local assemble_weights = function(entries, errout)
323
+	local ivs = {}
324
+
325
+	for _, ent in pairs(entries) do
326
+		if ivs[ent.file] ~= nil then
327
+			local sza = path_size(ivs[ent.file].source.file)
328
+			local szb = path_size(ent.source.file)
329
+			if sza < szb then
330
+				ivs[ent.file] = { weight = ent.weight, source = ent.source }
331
+			elseif sza == szb then
332
+				local namea = ivs[ent.file].source.manifest
333
+				local nameb = ent.source.manifest
334
+				if namea == nameb then
335
+					errout("warning: two conflicting weights for " .. ent.file .. " in " .. namea)
336
+				else
337
+					errout("warning: two conflicting weights for " .. ent.file .. " in " .. namea .. " and " .. nameb)
338
+				end
339
+			end
340
+		else
341
+			ivs[ent.file] = { weight = ent.weight, source = ent.source }
342
+		end
343
+	end
344
+
345
+	return ivs
346
+end
347
+
348
+local function usage()
349
+	print("usage: <this program> <input manifest> <output table>")
350
+end
351
+
352
+if arg[1] == nil or arg[2] == nil then
353
+	usage()
354
+	return
355
+end
356
+
357
+local taboutf = io.open(arg[2], "w")
358
+if taboutf == nil then
359
+	print("Could not open output file")
360
+	return
361
+end
362
+
363
+local tab = {}
364
+
365
+read_manifest(arg[1], tab, function(s) print(s) end)
366
+
367
+local weightmap = assemble_weights(tab, function(s) print(s) end)
368
+
369
+local cumweights = {}
370
+local cum = 0.0
371
+
372
+for file, wt in pairs(weightmap) do
373
+	cum = cum + wt.weight
374
+	table.insert(cumweights, { cum = cum, file = file, wt = wt })
375
+end
376
+
377
+for idx, ent in ipairs(cumweights) do
378
+	taboutf:write(tostring(ent.cum) .. " : " .. ent.file .. "\n")
379
+end
380
+
381
+taboutf:close()
382
+

+ 61
- 0
parse_table.lua View File

@@ -0,0 +1,61 @@
1
+
2
+local function read_table(filename, file_table, errout)
3
+	local function parse_line(line, file_table, errout)
4
+		local s, e = string.find(line, " : ")
5
+		if s == nil or e == nil then
6
+			errout("error: bad line")
7
+			return
8
+		end
9
+		local cum = tonumber(string.sub(line, 1, s - 1))
10
+		local file = string.sub(line, e + 1)
11
+		table.insert(file_table, { cum = cum, file = file })
12
+	end
13
+
14
+	local tabf = io.open(filename, "r")
15
+	if tabf == nil then
16
+		errout("could not open table file " .. filename)
17
+		return
18
+	end
19
+
20
+	for line in tabf:lines() do
21
+		parse_line(line, file_table, errout)
22
+	end
23
+
24
+	io.close(tabf)
25
+end
26
+
27
+local function search_table(file_table, cum)
28
+	local s = 1
29
+	local e = #file_table - 1
30
+	while true do
31
+		if s >= e then
32
+			return s
33
+		end
34
+		local sidx = math.floor((s + e) / 2)
35
+		if cum < file_table[sidx].cum then
36
+			e = sidx
37
+		else
38
+			s = sidx + 1
39
+		end
40
+	end
41
+end
42
+
43
+local ftab = {}
44
+
45
+read_table("outtab.txt", ftab, function(em) print(em) end)
46
+
47
+--for idx, ent in ipairs(ftab) do
48
+--	print(tostring(idx) .. " cwgt(" .. tostring(ent.file) .. ") = " .. tostring(ent.cum))
49
+--end
50
+
51
+local uw = ftab[#ftab - 1].cum
52
+
53
+math.randomseed(os.time())
54
+for i=1,100 do
55
+	local eidx = search_table(ftab, math.random() * uw)
56
+	local fname = ftab[eidx].file
57
+	print(fname)
58
+end
59
+
60
+return { read_table = read_table, search_table = search_table }
61
+

Loading…
Cancel
Save