fixed off-by-one bug
[swftools.git] / lib / action / listaction.c
blobb3309cec983a77745f284f866a718bf1980ef322
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <stdarg.h>
4 #include "action.h"
5 #include "compile.h"
8 #define print(x) {fputs(x,stdout);}
10 int gIndent;
11 #define INDENT_LEVEL 2
13 void println(const char *s, ...)
15 va_list ap;
16 int n = gIndent*INDENT_LEVEL;
18 while(n-- > 0)
19 putchar(' ');
21 va_start(ap, s);
22 vprintf(s, ap);
23 va_end(ap);
25 putchar('\n');
28 int fileOffset = 0;
30 int readUInt8(Buffer f)
32 return f->buffer[fileOffset++];
35 int readSInt8(Buffer f)
37 return (signed char)readUInt8(f);
40 int readSInt16(Buffer f)
42 return readUInt8(f) + readSInt8(f)*256;
45 int readUInt16(Buffer f)
47 return readUInt8(f) + (readUInt8(f)<<8);
50 long readSInt32(Buffer f)
52 return (long)readUInt8(f) + (readUInt8(f)<<8) + (readUInt8(f)<<16) + (readUInt8(f)<<24);
55 unsigned long readUInt32(Buffer f)
57 return (unsigned long)(readUInt8(f) + (readUInt8(f)<<8) + (readUInt8(f)<<16) + (readUInt8(f)<<24));
60 double readDouble(Buffer f)
62 double d;
63 unsigned char *p = (unsigned char *)&d;
65 p[4] = readUInt8(f);
66 p[5] = readUInt8(f);
67 p[6] = readUInt8(f);
68 p[7] = readUInt8(f);
69 p[0] = readUInt8(f);
70 p[1] = readUInt8(f);
71 p[2] = readUInt8(f);
72 p[3] = readUInt8(f);
74 return d;
77 char *readString(Buffer f)
79 int len = 0, buflen = 256;
80 char c, *buf, *p;
82 buf = (char *)malloc(sizeof(char)*256);
83 p = buf;
85 while((c=(char)readUInt8(f)) != '\0')
87 if(len==buflen)
89 buf = (char *)realloc(buf, sizeof(char)*(buflen+256));
90 buflen += 256;
91 p = buf+len;
94 *(p++) = c;
95 ++len;
98 *p = 0;
100 return buf;
103 void dumpBytes(Buffer f, int length)
105 int j=0, i, k;
106 unsigned char buf[16];
108 if(length==0)
109 return;
111 for(;;)
113 for(i=0; i<16; ++i)
115 printf("%02x ", buf[i] = readUInt8(f));
116 ++j;
118 if(j==length)
119 break;
122 if(j==length)
124 for(k=i+1; k<16; ++k)
125 print(" ");
127 ++i;
130 print(" ");
132 for(k=0; k<i; ++k)
133 if((buf[k] > 31) && (buf[k] < 128))
134 putchar(buf[k]);
135 else
136 putchar('.');
138 putchar('\n');
140 if(j==length)
141 break;
143 putchar('\n');
144 putchar('\n');
147 void printDoAction(Buffer f, int length);
149 char *dictionary[256];
151 int printActionRecord(Buffer f)
153 int length = 0, type;
155 printf("(%i)\t", fileOffset);
157 type = readUInt8(f);
159 if((type&0x80) == 0x80)
160 length = readUInt16(f);
162 switch(type)
164 case SWFACTION_ADD:
165 println("Add");
166 break;
167 case SWFACTION_SUBTRACT:
168 println("Subtract");
169 break;
170 case SWFACTION_MULTIPLY:
171 println("Multiply");
172 break;
173 case SWFACTION_DIVIDE:
174 println("Divide");
175 break;
176 case SWFACTION_EQUAL:
177 println("Equals");
178 break;
179 case SWFACTION_LESSTHAN:
180 println("Less Than");
181 break;
182 case SWFACTION_LOGICALAND:
183 println("And");
184 break;
185 case SWFACTION_LOGICALOR:
186 println("Or");
187 break;
188 case SWFACTION_LOGICALNOT:
189 println("Not");
190 break;
191 case SWFACTION_STRINGEQ:
192 println("String eq");
193 break;
194 case SWFACTION_STRINGLENGTH:
195 println("String Length");
196 break;
197 case SWFACTION_SUBSTRING:
198 println("Substring");
199 break;
200 case SWFACTION_POP:
201 println("Pop");
202 break;
203 case SWFACTION_INT:
204 println("Int");
205 break;
206 case SWFACTION_GETVARIABLE:
207 println("Get Variable");
208 break;
209 case SWFACTION_SETVARIABLE:
210 println("Set Variable");
211 break;
212 case SWFACTION_SETTARGETEXPRESSION:
213 println("Set Target Expression");
214 break;
215 case SWFACTION_STRINGCONCAT:
216 println("String Concat");
217 break;
218 case SWFACTION_GETPROPERTY:
219 println("Get Property");
220 break;
221 case SWFACTION_SETPROPERTY:
222 println("Set Property");
223 break;
224 case SWFACTION_DUPLICATECLIP:
225 println("Duplicate Clip");
226 break;
227 case SWFACTION_REMOVECLIP:
228 println("Remove Clip");
229 break;
230 case SWFACTION_TRACE:
231 println("Trace");
232 break;
233 case SWFACTION_STARTDRAGMOVIE:
234 println("Start Drag Movie");
235 break;
236 case SWFACTION_STOPDRAGMOVIE:
237 println("Stop Drag Movie");
238 break;
239 case SWFACTION_STRINGCOMPARE:
240 println("String Compare");
241 break;
242 case SWFACTION_RANDOM:
243 println("Random");
244 break;
245 case SWFACTION_MBLENGTH:
246 println("String MB Length");
247 break;
248 case SWFACTION_ORD:
249 println("Ord");
250 break;
251 case SWFACTION_CHR:
252 println("Chr");
253 break;
254 case SWFACTION_GETTIMER:
255 println("Get Timer");
256 break;
257 case SWFACTION_MBSUBSTRING:
258 println("MB Substring");
259 break;
260 case SWFACTION_MBORD:
261 println("MB Ord");
262 break;
263 case SWFACTION_MBCHR:
264 println("MB Chr");
265 break;
266 case SWFACTION_NEXTFRAME:
267 println("Next Frame");
268 break;
269 case SWFACTION_PREVFRAME:
270 println("Previous Frame");
271 break;
272 case SWFACTION_PLAY:
273 println("Play");
274 break;
275 case SWFACTION_STOP:
276 println("Stop");
277 break;
278 case SWFACTION_TOGGLEQUALITY:
279 println("Toggle Quality");
280 break;
281 case SWFACTION_STOPSOUNDS:
282 println("Stop Sounds");
283 break;
285 /* ops with args */
286 case SWFACTION_PUSHDATA:
288 int type;
289 int start = fileOffset;
291 while(fileOffset < start+length)
293 switch(type = readUInt8(f))
295 case 0: /* string */
296 println("Push String: %s", readString(f));
297 break;
298 case 1: /* property */
299 readUInt16(f); /* always 0? */
300 println("Push Property: %04x", readUInt16(f));
301 break;
302 case 2: /* null */
303 println("Push NULL");
304 break;
305 case 3: /* ??? */
306 println("Push type 3- ??");
307 break;
308 case 4:
309 println("Push register %i", readUInt8(f));
310 break;
311 case 5:
312 if(readUInt8(f))
313 println("Push true");
314 else
315 println("Push false");
316 break;
317 case 6: /* double */
318 println("Push %f", readDouble(f));
319 break;
320 case 7: /* int */
321 println("Push %i", readSInt32(f));
322 break;
323 case 8: /* dictionary */
324 println("Push \"%s\"", dictionary[readUInt8(f)]);
325 break;
326 case 9: /* dictionary */
327 println("Push \"%s\"", dictionary[readSInt16(f)]);
328 default:
329 println("unknown push type: %i", type);
332 break;
334 case SWFACTION_GOTOFRAME:
335 println("Goto Frame %i", readUInt16(f));
336 break;
337 case SWFACTION_GETURL:
339 char *url = readString(f);
340 println("Get URL \"%s\" target \"%s\"", url, readString(f));
341 break;
343 case SWFACTION_WAITFORFRAMEEXPRESSION:
344 println("Wait For Frame Expression, skip %i\n", readUInt8(f));
345 break;
346 case SWFACTION_BRANCHALWAYS:
347 println("Branch Always %i", readSInt16(f));
348 break;
349 case SWFACTION_GETURL2:
351 int flags = readUInt8(f);
353 const char *op = (flags & 0x80) ? "Get URL2 (loadvariables)" : "Get URL2";
354 const char *tgt = (flags & 0x40) ? " into target" : "";
356 switch(flags & 0x03)
358 case 0: println("%s%s (Don't send)", op, tgt); break;
359 case 1: println("%s%s (GET)", op, tgt); break;
360 case 2: println("%s%s (POST)", op, tgt); break;
363 break;
364 case SWFACTION_BRANCHIFTRUE:
365 println("Branch If True %i", readSInt16(f));
366 break;
367 case SWFACTION_CALLFRAME:
368 println("Call Frame");
369 dumpBytes(f, length);
370 break;
371 case SWFACTION_GOTOEXPRESSION:
372 print("Goto Expression");
373 if(readUInt8(f) == 1)
374 printf(" and Play\n");
375 else
376 printf(" and Stop\n");
377 break;
378 case SWFACTION_WAITFORFRAME:
380 int frame = readUInt16(f);
381 println("Wait for frame %i else skip %i", frame, readUInt8(f));
382 break;
384 case SWFACTION_SETTARGET:
385 println("Set Target %s", readString(f));
386 break;
387 case SWFACTION_GOTOLABEL:
388 println("Goto Label %s", readString(f));
389 break;
390 case SWFACTION_END:
391 return 0;
392 break;
394 /* f5 ops */
395 case SWFACTION_DELETE:
396 println("Delete");
397 break;
398 case SWFACTION_VAR:
399 println("Var");
400 break;
401 case SWFACTION_VAREQUALS:
402 println("Var assign");
403 break;
404 case SWFACTION_INITARRAY:
405 println("Init array");
406 break;
407 case SWFACTION_INITOBJECT:
408 println("Init object");
409 break;
410 case SWFACTION_CALLFUNCTION:
411 println("call function");
412 break;
413 case SWFACTION_RETURN:
414 println("return");
415 break;
416 case SWFACTION_MODULO:
417 println("modulo");
418 break;
419 case SWFACTION_NEW:
420 println("new");
421 break;
422 case SWFACTION_TYPEOF:
423 println("typeof");
424 break;
425 case SWFACTION_NEWADD:
426 println("new add");
427 break;
428 case SWFACTION_NEWLESSTHAN:
429 println("new less than");
430 break;
431 case SWFACTION_NEWEQUALS:
432 println("new equals");
433 break;
434 case SWFACTION_DUP:
435 println("dup");
436 break;
437 case SWFACTION_SWAP:
438 println("swap");
439 break;
440 case SWFACTION_GETMEMBER:
441 println("get member");
442 break;
443 case SWFACTION_SETMEMBER:
444 println("set member");
445 break;
446 case SWFACTION_INCREMENT:
447 println("increment");
448 break;
449 case SWFACTION_CALLMETHOD:
450 println("call method");
451 break;
452 case SWFACTION_BITWISEAND:
453 println("bitwise and");
454 break;
455 case SWFACTION_BITWISEOR:
456 println("bitwise or");
457 break;
458 case SWFACTION_BITWISEXOR:
459 println("bitwise xor");
460 break;
461 case SWFACTION_SHIFTLEFT:
462 println("shift left");
463 break;
464 case SWFACTION_SHIFTRIGHT:
465 println("shift right");
466 break;
467 case SWFACTION_SHIFTRIGHT2:
468 println("shift right 2");
469 break;
471 case SWFACTION_CONSTANTPOOL:
473 int i, n = readUInt16(f);
474 print("declare dictionary:");
476 for(i=0; i<n; ++i)
477 printf(" %s%c", dictionary[i]=readString(f), (i<n-1)?',':'\n');
479 break;
481 case SWFACTION_WITH:
483 println("with");
485 ++gIndent;
486 printDoAction(f, readUInt16(f));
487 --gIndent;
489 break;
491 case SWFACTION_DEFINEFUNCTION:
493 char *name = readString(f);
494 int n = readUInt16(f);
496 print("function ");
497 print(name);
498 putchar('(');
500 if(n > 0)
502 printf("%s", readString(f));
503 --n;
506 for(; n>0; --n)
507 printf(", %s", readString(f));
509 putchar(')');
510 putchar('\n');
512 ++gIndent;
513 printDoAction(f, readUInt16(f));
514 --gIndent;
516 break;
519 case SWFACTION_ENUMERATE:
520 println("enumerate");
521 break;
523 case SWFACTION_SETREGISTER:
524 println("set register %i", readUInt8(f));
525 break;
527 /* f6 actions */
528 case SWFACTION_INSTANCEOF:
529 println("instanceof");
530 break;
531 case SWFACTION_STRICTEQ:
532 println("strict_equals");
533 break;
534 case SWFACTION_ENUM2:
535 println("enum2");
536 break;
538 default:
539 println("Unknown Action: %02X", type);
540 dumpBytes(f, length);
543 return 1;
546 void printDoAction(Buffer f, int length)
548 int end;
550 if(!f)
551 return;
553 end = fileOffset + length;
555 while(fileOffset < end && printActionRecord(f))