forked from fdorg/flashdevelop
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCompiler.cs
More file actions
240 lines (187 loc) · 8.69 KB
/
Copy pathCompiler.cs
File metadata and controls
240 lines (187 loc) · 8.69 KB
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
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
/*
swfOP is an open source library for manipulation and examination of
Macromedia Flash (SWF) ActionScript bytecode.
Copyright (C) 2004 Florian Krüsch.
see Licence.cs for LGPL full text!
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
using System;
using System.Collections;
using System.IO;
using SwfOp.ByteCode.Actions;
namespace SwfOp.ByteCode
{
///<summary>
/// Compiler class, exposes one public method: <see cref="SwfOp.ByteCode.Compiler.Compile"/>.
/// </summary>
public class Compiler {
/// <summary>
/// Collaps sequence of single push actions into one multiple-push action
/// </summary>
private void CollapsPushActions(ArrayList actionRecord) {
int i = 0;
bool isPush;
while (i<(actionRecord.Count-1)) {
isPush = actionRecord[i] is ActionPush;
if (isPush) {
int j = i;
int count = 1;
do {
i++;
if (i<actionRecord.Count) {
isPush=(actionRecord[i] is ActionPush);
if (isPush) count++;
}
} while ((isPush)&&(i<actionRecord.Count));
if (count>1) {
ActionPush[] pushList = new ActionPush[count];
actionRecord.CopyTo(j,pushList,0,count);
actionRecord.RemoveRange(j,count);
ActionPushList pl = new ActionPushList(pushList);
actionRecord.Insert(j,pl);
i=j+1;
}
} else {
// recursively step through functions inner actions
ActionDefineFunction f = actionRecord[i] as ActionDefineFunction;
if (f!=null) CollapsPushActions(f.ActionRecord);
// and function2 of course
ActionDefineFunction2 f2 = actionRecord[i] as ActionDefineFunction2;
if (f2!=null) CollapsPushActions(f2.ActionRecord);
i++;
}
}
}
///<summary>
/// Inner struct for storing branch data.
/// </summary>
struct JumpPos {
public readonly int Position;
public readonly IJump Jump;
public JumpPos(int pos,IJump j) {
Position = pos;
Jump = j;
}
}
///<summary>
/// Calculate branch offsets.
///</summary>
private void CalcBranchOffsets(ArrayList actionRecord) {
if (actionRecord.Count<1) return;
ArrayList jumpList = new ArrayList();
Hashtable labelPos = new Hashtable();
int pos = 0;
for (int i=0; i<actionRecord.Count; i++) {
BaseAction action = (BaseAction) actionRecord[i];
ActionLabel label = action as ActionLabel;
IJump jump = action as IJump;
if (label!=null) {
labelPos[label.LabelId] = pos;
}
if (jump!=null) {
jumpList.Add(new JumpPos(pos,jump));
}
// recursively step through function blocks
ActionDefineFunction f = actionRecord[i] as ActionDefineFunction;
if (f!=null) CalcBranchOffsets(f.ActionRecord);
ActionDefineFunction2 f2 = actionRecord[i] as ActionDefineFunction2;
if (f2!=null) CalcBranchOffsets(f2.ActionRecord);
pos+=action.ByteCount;
}
for (int i=0; i<jumpList.Count; i++) {
JumpPos j = (JumpPos) jumpList[i];
int offset = (int)labelPos[j.Jump.LabelId]-j.Position-5;
j.Jump.Offset = offset;
}
}
///<summary>
/// Calculate size or offset for action blocks.
///</summary>
private void CalcBlockOffsets(ArrayList actionRecord) {
if (actionRecord.Count<1) return;
for (int i=0; i<actionRecord.Count; i++) {
BaseAction a = (BaseAction) actionRecord[i];
// action with
ActionWith aWith = a as ActionWith;
if (aWith!=null) {
int j=i;
int offset = 0;
do {
j++;
offset+=((BaseAction)actionRecord[j]).ByteCount;
} while ((actionRecord[j] as ActionEndWith)==null);
int oldOffset = aWith.BlockLength;
aWith.BlockLength = offset;
}
// action waitForFrame
ActionWaitForFrame aWait = a as ActionWaitForFrame;
if (aWait!=null) {
int j=i;
int count = 0;
BaseAction ca;
do {
j++;
ca = (BaseAction)actionRecord[j];
if ((ca.Code>=0)||(ca.Code==(int)ActionCode.PushList)) count++;
} while ( (ca as ActionEndWait) == null);
aWait.SkipCount = count;
}
// action waitForFrame2
ActionWaitForFrame2 aWait2 = a as ActionWaitForFrame2;
if (aWait2!=null) {
int j=i;
int count = 0;
BaseAction ca;
do {
j++;
ca = (BaseAction)actionRecord[j];
if ((ca.Code>=0)||(ca.Code==(int)ActionCode.PushList)) count++;
} while ( (ca as ActionEndWait) == null);
aWait2.SkipCount = count;
}
// action function
ActionDefineFunction f = actionRecord[i] as ActionDefineFunction;
if (f!=null) CalcBlockOffsets(f.ActionRecord);
// action function2
ActionDefineFunction2 f2 = actionRecord[i] as ActionDefineFunction2;
if (f2!=null) CalcBlockOffsets(f2.ActionRecord);
}
}
///<summary>
/// Compile list of Action objects to byte code.
///</summary>
/// <param name="actionRecord">List of <see cref="SwfOp.ByteCode.Actions.BaseAction">action objects</see></param>
public byte[] Compile(ArrayList actionRecord) {
// code blocks
CollapsPushActions(actionRecord);
CalcBranchOffsets(actionRecord);
CalcBlockOffsets(actionRecord);
// compile action-by-action
foreach (object o in actionRecord) {
BaseAction action = (BaseAction) o;
action.Compile(binWriter);
}
return memStream.ToArray();
}
// writer
private BinaryWriter binWriter;
private MemoryStream memStream;
///<summary>
/// Constructor.
///</summary>
public Compiler() {
memStream = new MemoryStream();
binWriter = new BinaryWriter(memStream,System.Text.Encoding.Default);
}
}
}