-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathterminfo-eval.lua
176 lines (162 loc) · 3.51 KB
/
terminfo-eval.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
return function(fmt, ...)
local params = table.pack(...)
local out = ''
local stack = {}
while true do
local skip, tail = fmt:match '^([^%%]*)%%(.*)$'
if not skip then break end
out = out .. skip
fmt = tail
repeat
local tail = fmt:match '^%?(.*)$'
if tail then
fmt = tail
break
end
local param, tail = fmt:match '^p([0-9])(.*)$'
if param then
fmt = tail
stack[#stack + 1] = params[tonumber(param)]
break
end
local num, tail = fmt:match '^{([0-9]*)}(.*)$'
if num then
fmt = tail
stack[#stack + 1] = tonumber(num)
break
end
local op, tail = fmt:match '^([%+%-%*/m&|^=<>AO])(.*)$'
if op then
fmt = tail
local a, b = stack[#stack - 1], stack[#stack]
stack[#stack] = nil
stack[#stack] = nil
local r
if op == '+' then
r = a + b
elseif op == '-' then
r = a - b
elseif op == '*' then
r = a * b
elseif op == '/' then
r = a / b
elseif op == 'm' then
r = a % b
elseif op == '&' then
r = bit32.band(a, b)
elseif op == '|' then
r = bit32.bor(a, b)
elseif op == '^' then
r = bit32.bxor(a, b)
elseif op == '=' then
r = a == b and 1 or 0
elseif op == '<' then
r = a < b and 1 or 0
elseif op == '>' then
r = a > b and 1 or 0
elseif op == 'A' then
r = (a ~= 0 and b ~= 0) and 1 or 0
elseif op == 'O' then
r = (a ~= 0 or b ~= 0) and 1 or 0
else
error('Unhandled operand (should never happen): ' .. op)
end
stack[#stack + 1] = r
break
end
local tail = fmt:match '^t(.*)$'
if tail then
fmt = tail
local cond = stack[#stack] ~= 0
stack[#stack] = nil
if not cond then
local nesting = 0
local continue = true
while continue do
repeat
local tail = fmt:match '^[^%%]*%%(.*)$'
if not tail then
continue = false
break
end
fmt = tail
local tail = fmt:match '^%?(.*)$'
if tail then
fmt = tail
nesting = nesting + 1
break
end
local tail = fmt:match '^;(.*)$'
if tail then
fmt = tail
if nesting == 0 then
continue = false
break
end
nesting = nesting - 1
break
end
local tail = fmt:match '^e(.*)$'
if tail and nesting == 0 then
fmt = tail
break
end
until true
end
end
break
end
local tail = fmt:match '^e(.*)$'
if tail then
fmt = tail
local nesting = 0
local continue = true
while continue do
repeat
local tail = fmt:match '^[^%%]*%%(.*)$'
if not tail then
continue = false
break
end
fmt = tail
local tail = fmt:match '^%?(.*)$'
if tail then
fmt = tail
nesting = nesting + 1
break
end
local tail = fmt:match '^;(.*)$'
if tail then
fmt = tail
if nesting == 0 then
continue = false
break
end
nesting = nesting - 1
break
end
until true
end
break
end
local df, tail = fmt:match '^(:?[# 0+-]*[0-9]*%.?[0-9]*[doxXs])(.*)'
if df then
fmt = tail
local v = stack[#stack]
stack[#stack] = nil
out = out .. ('%' .. df):format(v)
break
end
local tail = fmt:match '^i(.*)$'
if tail then
fmt = tail
params[1] = params[1] + 1
params[2] = params[2] + 1
break
end
error(('unhandled terminfo format: %q'):format(fmt))
until true
end
out = out .. fmt
return out
end