File: vm.lua

package info (click to toggle)
eja 9.5.20-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye, buster, stretch
  • size: 1,340 kB
  • ctags: 3,142
  • sloc: ansic: 15,010; makefile: 255
file content (225 lines) | stat: -rw-r--r-- 5,830 bytes parent folder | download
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
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
-- Copyright (C) 2007-2015 by Ubaldo Porcheddu <ubaldo@eja.it>


eja.lib.export='ejaVmFileExport'
eja.help.export='vm export (file)'


function ejaVmInt2Hex(int) 	return ejaSprintf('i%X',int) end

function ejaVmByte2Hex(int) 	return ejaSprintf('b%X',int) end

function ejaVmInstr2Hex(int) 	return ejaSprintf('I%X',int) end

function ejaVmSize2Hex(int) 	return ejaSprintf('s%X',int) end

function ejaVmNum2Hex(int) 	return ejaSprintf('n%X',int) end


function ejaVmString2Hex(data)
 local out='S'
 local i
 for i=1,#data do out=out..ejaSprintf('%02X',data:byte(i)) end
 return out
end 


function ejaVmHex2Byte(little,hex,len)
 local o=''
 local n=tonumber(hex,16)
 for i=1,len do
  o=string.char(n%256)..o
  n=math.floor(n/256)
 end
 if little > 0 then o=o:reverse() end 
 return o
end


function ejaVmByte2Int(little,data)
 local n=0
 if little > 0 then
  for i=#data,1,-1 do n=n+tonumber(data:byte(i)*(256^i)) end
 else
  for i=1,#data do n=n+(data:byte(i)*(256^i)) end
 end
 return n/256
end


function ejaVmFunction(h,d,pos)	--header, data, position
 local o={}
 local i=0
 local z=0
 local p=pos
 local debug=false

 o[#o+1]=ejaVmInt2Hex(ejaVmByte2Int(h.endian,d:sub(p,p+h.int-1)));		p=p+h.int;	--first line
 o[#o+1]=ejaVmInt2Hex(ejaVmByte2Int(h.endian,d:sub(p,p+h.int-1)));		p=p+h.int;	--last line
 o[#o+1]=ejaVmByte2Hex(d:byte(p));						p=p+1;		--num params
 o[#o+1]=ejaVmByte2Hex(d:byte(p));						p=p+1;		--is vararg
 o[#o+1]=ejaVmByte2Hex(d:byte(p));						p=p+1;		--max stack size

 if debug then o[#o+1]='\ninstr\n' end	
 z=ejaVmByte2Int(h.endian,d:sub(p,p+h.int-1));
 o[#o+1]=ejaVmInt2Hex(z);							p=p+h.int;	--length of Instruction block
 for n=1,z do
  o[#o+1]=ejaVmInstr2Hex(ejaVmByte2Int(h.endian,d:sub(p,p+h.Instr-1)));	p=p+h.Instr;	--Instruction
 end

 if debug then o[#o+1]='\nconst\n' end	
 z=ejaVmByte2Int(h.endian,d:sub(p,p+h.int-1));
 o[#o+1]=ejaVmInt2Hex(z);							p=p+h.int;	--length of constant
 for n=1,z do
  local cType=d:byte(p);
  o[#o+1]=ejaVmByte2Hex(cType);						p=p+1;		--const type
  if cType == 4 then
   local l=ejaVmByte2Int(h.endian,d:sub(p,p+h.size-1));
   o[#o+1]=ejaVmSize2Hex(l);						p=p+h.size;	--string length
   if l > 0 then
    o[#o+1]=ejaVmString2Hex(d:sub(p,p+l-1));				p=p+l;		--string
   end
  end
  if cType == 3 then
   o[#o+1]=ejaVmNum2Hex(ejaVmByte2Int(h.endian,d:sub(p,p+h.num-1)));	p=p+h.num;	--number
  end
  if cType == 1 then
   o[#o+1]=ejaVmByte2Hex(d:byte(p));					p=p+1;		--boolean
  end
  if cType == 0 then end								--nil
 end

 if debug then o[#o+1]='\nproto\n' end	
 z=ejaVmByte2Int(h.endian,d:sub(p,p+h.int-1));
 o[#o+1]=ejaVmInt2Hex(z);							p=p+h.int;	--length of function 
 for n=1,z do
  local t,n=ejaVmFunction(h,d,p)
  p=p+n
  o[#o+1]=t
 end
 
 if debug then o[#o+1]='\nupvalue\n' end
 z=ejaVmByte2Int(h.endian,d:sub(p,p+h.int-1));
 o[#o+1]=ejaVmInt2Hex(z);							p=p+h.int;	--length of upvalues
 for n=1,z do
  o[#o+1]=ejaVmByte2Hex(d:byte(p));					p=p+1;		--stack
  o[#o+1]=ejaVmByte2Hex(d:byte(p));					p=p+1;		--idx
 end

 if debug then o[#o+1]='\nsource\n' end	
 l=ejaVmByte2Int(h.endian,d:sub(p,p+h.size-1));
 o[#o+1]=ejaVmSize2Hex(0);							p=p+h.size;	--string length
 if l > 0 then
  p=p+l;										--string
 end
 
 if debug then o[#o+1]='\nline info\n' end
 z=ejaVmByte2Int(h.endian,d:sub(p,p+h.int-1));
 o[#o+1]=ejaVmInt2Hex(0);							p=p+h.int;	--length of line
 for n=1,z do
  p=p+h.int;										--begin
 end

  
 if debug then o[#o+1]='\nlocals\n' end
 z=ejaVmByte2Int(h.endian,d:sub(p,p+h.int-1));
 o[#o+1]=ejaVmInt2Hex(0);							p=p+h.int;	--length of local vars
 for n=1,z do
  local l=ejaVmByte2Int(h.endian,d:sub(p,p+h.size-1));
   p=p+h.size;										--string length
  if l > 0 then
   p=p+l;										--string
  end
  p=p+h.int;										--begin
  p=p+h.int;										--end
 end

 if debug then o[#o+1]='\nupvalues\n' end
 z=ejaVmByte2Int(h.endian,d:sub(p,p+h.int-1));
 o[#o+1]=ejaVmInt2Hex(0);							p=p+h.int;	--length of upvalues
 for n=1,z do
  local l=ejaVmByte2Int(h.endian,d:sub(p,p+h.size-1));
  p=p+h.size;										--string length
  p=p+l;										--string
 end

 return table.concat(o),p-pos
end


function ejaVmHeader(data)
 local h={}
 h.version=data:byte(5);
 h.format=data:byte(6)
 h.endian=data:byte(7)
 h.int=data:byte(8)	
 h.size=data:byte(9)		
 h.Instr=data:byte(10)	
 h.num=data:byte(11)	
 h.integral=data:byte(12)
 return h  
end


function ejaVmExport(data)
 local o='ejaVM';
 local h=ejaVmHeader(data)
 local t,n=ejaVmFunction(h,data,12+6+1)
 return o..t
end


function ejaVmImport(data)
 if data:sub(1,5) == 'ejaVM' then
  local o={}
  local h=''
  o[#o+1]=string.dump(loadstring("do end")):sub(1,18)
  h=ejaVmHeader(o[1])
  for k,v in data:gmatch('([nbiIsS])([^nbiIsS]+)') do 
   if k == 'b' then o[#o+1]=ejaVmHex2Byte(h.endian,v,1) end
   if k == 'n' then o[#o+1]=ejaVmHex2Byte(h.endian,v,h.num) end
   if k == 'i' then o[#o+1]=ejaVmHex2Byte(h.endian,v,h.int) end
   if k == 'I' then o[#o+1]=ejaVmHex2Byte(h.endian,v,h.Instr) end
   if k == 's' then o[#o+1]=ejaVmHex2Byte(h.endian,v,h.size) end
   if k == 'S' then 
    for c in v:gmatch('..') do
     o[#o+1]=string.char(tonumber(c,16))
    end   
   end
  end 
  return table.concat(o)
 else
  return nil
 end
end


function ejaVmFileExport(file)
 local f=file or eja.opt.export or nil
 if f then
  local data=ejaFileRead(f) 
  if f:sub(-4) == '.lua' then f=f:sub(1,-5) end
  if data and data:sub(1,5) ~= 'ejaVM' then
   if data:sub(1,4) == string.char(27,76,117,97) then
    data=ejaVmExport(data)
   else
    data=ejaVmExport(string.dump(loadstring(data)))
   end
   ejaFileWrite(f..'.eja',data)
  end
 end 
end


function ejaVmFileLoad(f)
 local data=ejaFileRead(f)
 if data then
  if data:sub(1,5) == 'ejaVM' then
   data=ejaVmImport(data)
  end
 end
 local ejaScriptRun=assert(loadstring(data))
 if ejaScriptRun then ejaScriptRun() end
end