r7 - in /packages/flasm: ./ branches/ branches/upstream/
branches/upstream/current/ branches/upstream/current/flasm.c tags/
pabs-guest at users.alioth.debian.org
pabs-guest at users.alioth.debian.org
Fri Jun 2 09:04:56 UTC 2006
Author: pabs-guest
Date: Fri Jun 2 09:04:52 2006
New Revision: 7
URL: http://svn.debian.org/wsvn/?sc=1&rev=7
Log:
[svn-inject] Installing original source of flasm
Added:
packages/flasm/
packages/flasm/branches/
packages/flasm/branches/upstream/
packages/flasm/branches/upstream/current/
packages/flasm/branches/upstream/current/flasm.c
packages/flasm/tags/
Added: packages/flasm/branches/upstream/current/flasm.c
URL: http://svn.debian.org/wsvn/packages/flasm/branches/upstream/current/flasm.c?rev=7&op=file
==============================================================================
--- packages/flasm/branches/upstream/current/flasm.c (added)
+++ packages/flasm/branches/upstream/current/flasm.c Fri Jun 2 09:04:52 2006
@@ -1,0 +1,1819 @@
+/*
+flasm, command line assembler & disassembler of flash actionscript bytecode
+Copyright (c) 2001 Opaque Industries, (c) 2002-2005 Igor Kogan, (c) 2005 Wang Zhen
+All rights reserved. See LICENSE.TXT for terms of use.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <time.h>
+#include <unistd.h>
+
+#ifdef MEMWATCH
+#include "memwatch.h"
+#endif
+
+#if defined(__DJGPP__) || defined(__MINGW32__)
+#include <conio.h>
+#endif
+
+#include "zlib.h"
+#include "util.h"
+#include "flasm.h"
+
+extern FILE *yyin;
+extern void skipProtected(FILE * f, unsigned long int length);
+extern void disassembleSWF(FILE * in, char *fname);
+
+int swfVersion;
+
+char *inputName; /* actual command-line parameter */
+static char *updateName = NULL; /* swf file name found in disassembly's first line (movie foo.swf...) */
+static char *tempName = NULL; /* temporary file during assembling */
+static char *flmName = NULL; /* temporary disassembly during update */
+static char *backupName = NULL; /* foo.$wf if foo.swf is updated */
+static FILE *updateFile = NULL;
+static FILE *tempFile = NULL;
+static FILE *inputFile = NULL;
+static FILE *logFile = NULL;
+
+static char swfHeader[4];
+static long int flength = 0;
+static char backupCreated = 0;
+
+char wasCompressed = 0;
+char compressAfter = 0;
+int mode;
+
+/* ini entries */
+int showoffset = 0, hexoffset = 0, boutput = 0, literalconstants = 0, literalregisters = 1, clearregisterargs = 1, logmode = 0;
+static char *logto = NULL, *flaplayer = NULL, *flabrowser = NULL, *flatest = NULL;
+static char flapath[1000];
+
+void yyerror(char *s);
+void warning(char *s);
+int yyparse(void);
+
+static byte *output = NULL;
+
+static void decompressSWF(FILE * f, char *fname);
+static void compressSWF(FILE * f, char *fname);
+
+static long int defineMCLengthPos = 0;
+static long int buttonLengthPos = 0;
+static long int buttonLastOffsetPos = 0;
+static long int placeMCLengthPos = 0;
+static long int MCAllEventsPos = 0;
+static long int len;
+
+static unsigned int nLabels = 0;
+struct _label {
+ char *name;
+ /* offset >=0 if actual label definition, -1 if predefinition from branch */
+ long int offset;
+};
+static struct _label *labels = NULL;
+
+static void waitUserInput(void)
+{
+#if defined(__DJGPP__) || defined(__MINGW32__)
+ /* make sure we have kbhit(), otherwise do nothing */
+ fprintf(stderr, "Hit any key to continue..");
+ while (!kbhit()) {
+#ifdef __DJGPP__
+ /*
+ cygwin/mingw don't have pause()
+ it seems also no need for it there,
+ since kbhit() looping doesn't hang the CPU
+ djgpp executables, however, do need it
+ */
+ pause();
+#endif
+ }
+#endif
+}
+
+unsigned long int nStrings = 0;
+char **aStrings = NULL;
+
+static void mexit(int msg)
+{
+ unsigned long int i;
+ for (i = 0; i < nStrings; ++i)
+ free(aStrings[i]);
+
+ if (output != NULL)
+ free(output);
+
+ if (aStrings != NULL)
+ free(aStrings);
+
+ if (nLabels > 0 && labels != NULL)
+ free(labels);
+
+ exit(msg);
+}
+
+void tellUser(int isError, char *s, ...)
+{
+ va_list ap;
+ static int usestderr = 1;
+ static int firsttime = 1;
+
+ if (logto != NULL && firsttime == 1) {
+ firsttime = 0;
+ if (logmode == 0)
+ logFile = fopen(logto, "ab");
+ else
+ logFile = fopen(logto, "wb");
+
+ if (logFile == NULL)
+ fprintf(stderr, "Couldn't write to log file %s\nUsing stderr instead\n", logto);
+ else {
+ usestderr = 0;
+ if (logmode == 0) {
+ time_t now;
+ time(&now);
+ fprintf(logFile, "________________________\n%.24s\n¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯\n", ctime(&now));
+ }
+ }
+ }
+
+ if (s != NULL && strlen(s) > 0) {
+ va_start(ap, s);
+ if (usestderr) {
+ vfprintf(stderr, s, ap);
+ fputc('\n', stderr);
+ }
+ else {
+ vfprintf(logFile, s, ap);
+ fputc('\n', logFile);
+ }
+ va_end(ap);
+ }
+
+ if (isError) {
+ if (mode >= MODE_IDE && usestderr)
+ waitUserInput();
+
+ if (tempFile != NULL) {
+ fclose(tempFile);
+ remove(tempName);
+ }
+
+ if (updateFile != NULL)
+ fclose(updateFile);
+
+ if (wasCompressed && backupCreated && updateName != NULL && access(backupName, R_OK) == 0) {
+ remove(updateName);
+ rename(backupName, updateName);
+ }
+
+ if (logFile != NULL)
+ fclose(logFile);
+
+ mexit(EXIT_FAILURE);
+ }
+}
+
+char *mstrdup(const char *String)
+{
+ SUREALLOC(nStrings, aStrings, sizeof (char *));
+
+ if (String == NULL) {
+ if ((aStrings[nStrings] = malloc(256)) == NULL)
+ tellUser(1, "Not enough memory to allocate a string");
+ }
+ else {
+ size_t slen = strlen(String);
+
+ if ((aStrings[nStrings] = malloc(slen + 1)) != NULL)
+ memcpy(aStrings[nStrings], String, slen + 1);
+ else
+ tellUser(1, "Not enough memory to allocate a string");
+ }
+
+ return aStrings[nStrings++];
+}
+
+static unsigned int newLabel(char *name, long int offset)
+{
+ unsigned int i = nLabels;
+
+ /* first search if label exists, and update offset if needed */
+ if (name != NULL && nLabels>0) {
+ do {
+ i--;
+ if (labels[i].name != NULL && strcmp(name, labels[i].name) == 0) {
+ if (offset >= 0) {
+ if (labels[i].offset == -1)
+ labels[i].offset = offset;
+ else
+ yyerror("Label defined twice");
+ }
+ return i;
+ }
+ } while (i>0);
+ }
+
+ SUREALLOC(nLabels, labels, sizeof (struct _label));
+ labels[nLabels].name = name;
+ labels[nLabels].offset = offset;
+ return (nLabels++);
+}
+
+void addLabel(char *label)
+{
+ newLabel(label, len);
+}
+
+int branchTarget(char *label)
+{
+ return writeShort(newLabel(label, -1));
+}
+
+int addNumLabel(int numLabel)
+{
+ /* numerical offset given in a branch */
+
+ if (len + numLabel + 2 < 0)
+ yyerror("Branch target out of range");
+
+ return writeShort(newLabel(NULL, len + numLabel + 2));
+}
+
+int writeByte(byte num)
+{
+ if (len % OUTPUT_INC == 0)
+ output = realloc(output, len + OUTPUT_INC);
+
+ output[len++] = num;
+ return 1;
+}
+
+int writeShort(unsigned int num)
+{
+ writeByte(num & 0xff);
+ writeByte((num >> 8) & 0xff);
+ return 2;
+}
+
+int writeFloat(float num)
+{
+ byte *p = (byte *) #
+
+ if (byteorder == FLASM_BIG_ENDIAN) {
+ writeByte(p[3]);
+ writeByte(p[2]);
+ writeByte(p[1]);
+ writeByte(p[0]);
+ }
+ else {
+ writeByte(p[0]);
+ writeByte(p[1]);
+ writeByte(p[2]);
+ writeByte(p[3]);
+ }
+
+ return 4;
+}
+
+int writeDouble(double num)
+{
+ byte *p = (byte *) #
+
+ if (byteorder == FLASM_BIG_ENDIAN) {
+ writeByte(p[3]);
+ writeByte(p[2]);
+ writeByte(p[1]);
+ writeByte(p[0]);
+ writeByte(p[7]);
+ writeByte(p[6]);
+ writeByte(p[5]);
+ writeByte(p[4]);
+ }
+ else {
+ writeByte(p[4]);
+ writeByte(p[5]);
+ writeByte(p[6]);
+ writeByte(p[7]);
+ writeByte(p[0]);
+ writeByte(p[1]);
+ writeByte(p[2]);
+ writeByte(p[3]);
+ }
+
+ return 8;
+}
+
+int writeLongInt(long int num)
+{
+ byte *p = (byte *) #
+
+ if (byteorder == FLASM_BIG_ENDIAN) {
+ writeByte(p[3]);
+ writeByte(p[2]);
+ writeByte(p[1]);
+ writeByte(p[0]);
+ }
+ else {
+ writeByte(p[0]);
+ writeByte(p[1]);
+ writeByte(p[2]);
+ writeByte(p[3]);
+ }
+
+ return 4;
+}
+
+int writeString(char *str)
+{
+ int i;
+
+ for (i = 0; str[i] != '\0'; ++i)
+ writeByte((byte) str[i]);
+
+ writeByte(0);
+
+ return i + 1;
+}
+
+unsigned int nConstants = 0;
+static char *constants[MAX_CONSTANTS];
+
+void addConstant(char *str)
+{
+ constants[nConstants] = str;
+ ++nConstants;
+
+ if (nConstants > MAX_CONSTANTS)
+ yyerror("Too many constants");
+}
+
+unsigned int writeConstants(void)
+{
+ unsigned int i;
+ unsigned long int clen = 2;
+
+ writeByte(SWFACTION_CONSTANTPOOL);
+ /* length */
+ writeShort(0);
+ writeShort(nConstants);
+
+ for (i = 0; i < nConstants; ++i)
+ clen += writeString(constants[i]);
+
+ if (clen < 65533)
+ patchLength((unsigned int) clen, (unsigned int) clen);
+ else
+ tellUser(1, "Constant pool exceeds 64k");
+
+ return (unsigned int) clen + 3;
+}
+
+unsigned int writePushString(char *str)
+{
+ unsigned int i;
+
+ for (i = 0; i < nConstants; ++i) {
+ if (strcmp(constants[i], str) == 0)
+ break;
+ }
+
+ if (i < nConstants) {
+ if (i < 256) {
+ /* constant, 1-byte reference */
+ writeByte(0x08);
+ writeByte((byte) i);
+ return 2;
+ }
+ else {
+ /* constant, 2-byte reference */
+ writeByte(0x09);
+ writeShort(i);
+ return 3;
+ }
+ }
+
+ /* string */
+ writeByte(0);
+ return writeString(str) + 1;
+}
+
+static void patchTargets(void)
+{
+ long int i = 0;
+
+ while (i < len) {
+ Action op = (Action) output[i++];
+ if (op & 0x80) {
+ unsigned int blocklen = S16(output + i);
+ i += 2;
+
+ if (op == SWFACTION_BRANCHALWAYS || op == SWFACTION_BRANCHIFTRUE) {
+ long int offset;
+ unsigned int target = S16(output+i);
+
+ if (labels[target].offset < 0) {
+ char msg[256] = "Label not found: ";
+ yyerror(strcat(msg, labels[target].name));
+ }
+
+ offset = labels[target].offset - (i + 2);
+ if (offset > 32767 || offset < -32768) {
+ char msg[256] = "Label too far away from branch: ";
+ yyerror(strcat(msg, labels[target].name));
+ }
+
+ output[i] = (byte) (offset & 0xff);
+ output[i+1] = (byte) ((offset >> 8) & 0xff);
+ }
+ i += blocklen;
+ }
+ }
+}
+
+static int flput(char b)
+{
+ ++flength;
+ return fputc(b, tempFile);
+}
+
+static void flputShort(unsigned int w)
+{
+ fputc(0xff & w, tempFile);
+ fputc(0xff & (w >> 8), tempFile);
+ flength += 2;
+}
+
+static void flputLong(unsigned long int l)
+{
+ fputc(0xff & l, tempFile);
+ fputc(0xff & (l >> 8), tempFile);
+ fputc(0xff & (l >> 16), tempFile);
+ fputc(0xff & (l >> 24), tempFile);
+ flength += 4;
+}
+
+static void flputString(char *s)
+{
+ fwrite(s, strlen(s)+1, 1, tempFile);
+ flength += strlen(s)+1;
+}
+
+static int dupByte(void)
+{
+ return flput(fgetc(updateFile));
+}
+
+static unsigned int dupWord(void)
+{
+ int b1, b2;
+ b1 = fgetc(updateFile);
+ flput(b1);
+ b2 = fgetc(updateFile);
+ flput(b2);
+ return ((unsigned int) b1 + ((unsigned int) b2 << 8));
+}
+
+static unsigned long int dupLong(void)
+{
+ return ((unsigned long int) dupWord() + ((unsigned long int) dupWord() << 16));
+}
+
+static void dupBuffered(unsigned long int length)
+{
+ static byte dupBuffer[MAX_BUFFER];
+
+ flength += length;
+
+ while (length > MAX_BUFFER) {
+ if (fread(dupBuffer, 1, MAX_BUFFER, updateFile) == MAX_BUFFER) {
+ fwrite(dupBuffer, 1, MAX_BUFFER, tempFile);
+ length -= MAX_BUFFER;
+ }
+ else
+ yyerror("Couldn't update because of unexpected SWF structure");
+ }
+
+ if (length > 0) {
+ if (fread(dupBuffer, 1, length, updateFile) == length)
+ fwrite(dupBuffer, 1, length, tempFile);
+ else
+ yyerror("Couldn't update because of unexpected SWF structure");
+ }
+}
+
+void patchLength(unsigned int back, unsigned int blen)
+{
+ output[len - back - 1] = (blen >> 8) & 0xff;
+ output[len - back - 2] = blen & 0xff;
+}
+
+void patchFlag(unsigned int back, byte flag)
+{
+ output[len - back - 1] = flag;
+}
+
+void patchFrameLoaded(unsigned int back, int numActions)
+{
+ if (numActions > 0 || numActions < 256)
+ output[len - back - 1] = (byte) numActions;
+ else
+ yyerror("IfFrameLoaded block larger then 255 bytes is not allowed");
+}
+
+static void updateTmpLength(long int lenpos, long int reallen)
+{
+ long int curpos;
+ curpos = ftell(tempFile);
+
+ fseek(tempFile, lenpos, SEEK_SET);
+
+ /* update long length */
+ /* dont use flput to not affect the file size calculation */
+ fputc((reallen & 0xff), tempFile);
+ fputc((reallen >> 8) & 0xff, tempFile);
+ fputc((reallen >> 16) & 0xff, tempFile);
+ fputc((reallen >> 24) & 0xff, tempFile);
+
+ fseek(tempFile, curpos, SEEK_SET);
+}
+
+static void updateShort(long int lenpos, unsigned int reallen)
+{
+ long int curpos = ftell(tempFile);
+
+ fseek(tempFile, lenpos, SEEK_SET);
+
+ /* update short length */
+ /* dont use flput to not affect the file size calculation */
+ fputc(reallen & 0xff, tempFile);
+ fputc((reallen >> 8) & 0xff, tempFile);
+
+ fseek(tempFile, curpos, SEEK_SET);
+}
+
+static void flushOutput(void)
+{
+ patchTargets();
+
+ if (fwrite(output, 1, (size_t) len, tempFile) != (size_t) len)
+ tellUser(1, "Error writing action block");
+
+ flength += len;
+
+ len = 0;
+
+ if (nLabels > 0) {
+ nLabels = 0;
+ free(labels);
+ labels = NULL;
+ }
+
+ nConstants = 0;
+}
+
+static void writeTagHeader(unsigned int type, unsigned long int length)
+{
+ if (length >= 63
+ || type == TAG_DEFINEBITSLOSSLESS
+ || type == TAG_DEFINEBITSLOSSLESS2
+ || type == TAG_SOUNDSTREAMBLOCK) {
+ /*
+ long length, and also workaround for a really strange bug in flash player:
+ the above tags must always have long length to work
+ */
+ flputShort((type << 6) + 63);
+ flputLong(length);
+ }
+ else {
+ /* short length */
+ flputShort((type << 6) + length);
+ }
+}
+
+static int handledTag(unsigned int tag)
+{
+ return (tag == TAG_PROTECT
+ || tag == TAG_ENABLEDEBUGGER
+ || tag == TAG_ENABLEDEBUGGER2
+ || tag == TAG_SCRIPTLIMITS
+ || tag == TAG_FILEATTRIBUTES
+ || tag == TAG_METADATA);
+}
+
+static unsigned long int findNextTag(unsigned int typeneeded)
+{
+ /*
+ dumps all tags of the updateFile to the tempFile
+ until required tag is found, returns its length
+ */
+ unsigned int type;
+ unsigned long int length;
+
+ while (!feof(updateFile)) {
+ parseTagHeader(updateFile, &type, &length);
+ if (type == typeneeded)
+ return length;
+ if (handledTag(type))
+ skipProtected(updateFile, length);
+ else {
+ writeTagHeader(type, length);
+ dupBuffered(length);
+ }
+ }
+ tellUser(1, "Couldn't update because of unexpected SWF structure:\nunexpected end of SWF looking for Tag %04x", typeneeded);
+ return (0);
+}
+
+static unsigned long int findNextTags(unsigned int *typefound, int numtypes, ...)
+{
+ /*
+ dumps all blocks of the updateFile to the tempFile
+ until one of the required tags is found, returns its length
+ */
+ va_list typelist;
+ unsigned int type;
+ unsigned long int length;
+ int i;
+
+ while (!feof(updateFile)) {
+ parseTagHeader(updateFile, &type, &length);
+ va_start(typelist, numtypes);
+ for (i = 1; i <= numtypes; i++) {
+ if (type == va_arg(typelist, unsigned int)) {
+ *typefound = type;
+ va_end(typelist);
+ return length;
+ }
+ }
+ va_end(typelist);
+
+ if (handledTag(type))
+ skipProtected(updateFile, length);
+ else {
+ writeTagHeader(type, length);
+ dupBuffered(length);
+ }
+ }
+ tellUser(1, "Couldn't update because of unexpected SWF structure:\nunexpected end of SWF.");
+ return (0);
+}
+
+void writeDoAction()
+{
+ unsigned long int oldLength = findNextTag(TAG_DOACTION);
+
+ /* skip old action */
+ skipProtected(updateFile, oldLength);
+
+ writeTagHeader(TAG_DOACTION, len);
+
+ /* write bison output from buffer to file and empty buffer */
+ flushOutput();
+}
+
+void writeInitMC(unsigned int clipID)
+{
+ unsigned int oldID;
+ unsigned long int oldLength = findNextTag(TAG_INITMOVIECLIP);
+
+ writeTagHeader(TAG_INITMOVIECLIP, len + 2);
+
+ oldID = dupWord();
+ if (oldID != clipID)
+ tellUser(1, "Couldn't update because of unexpected SWF structure:\nold initMovieClip ID %u doesn't match new ID %u", oldID, clipID);
+
+ skipProtected(updateFile, oldLength - 2);
+
+ flushOutput();
+}
+
+static unsigned int bitPos;
+static unsigned int bitBuf;
+
+static unsigned int dupBits(unsigned int n)
+{
+ unsigned long int v = 0;
+
+ while (n > bitPos) {
+ n -= bitPos;
+ v |= bitBuf << n;
+ bitBuf = (unsigned int) dupByte();
+ bitPos = 8;
+ }
+
+ bitPos -= n;
+ v |= bitBuf >> bitPos;
+ bitBuf &= 0xff >> (8 - bitPos);
+ /* never need more than 16 bits */
+ return (unsigned int) v;
+}
+
+static void dupMatrix(void)
+{
+ bitPos = 8;
+ bitBuf = (unsigned int) dupByte();
+
+ if (dupBits(1))
+ dupBits(dupBits(5) * 2);
+ if (dupBits(1))
+ dupBits(dupBits(5) * 2);
+ dupBits(dupBits(5) * 2);
+}
+
+static void dupColorTransform(void)
+{
+ unsigned int needAdd, needMul, nBits;
+
+ bitPos = 8;
+ bitBuf = (unsigned int) dupByte();
+
+ needAdd = dupBits(1);
+ needMul = dupBits(1);
+ nBits = dupBits(4);
+ if (needMul)
+ dupBits(nBits * 4);
+ if (needAdd)
+ dupBits(nBits * 4);
+}
+
+static void dupFilters(void)
+{
+ byte numfilters = dupByte();
+ while(numfilters--)
+ switch(dupByte()){
+ case FILTER_DROPSHADOW:
+ dupBuffered(23);
+ break;
+ case FILTER_BLUR:
+ dupBuffered(9);
+ break;
+ case FILTER_GLOW:
+ dupBuffered(15);
+ break;
+ case FILTER_BEVEL:
+ dupBuffered(27);
+ break;
+ case FILTER_GRADIENTGLOW:
+ dupBuffered(dupByte()*5 + 19);
+ break;
+ case FILTER_ADJUSTCOLOR:
+ dupBuffered(80);
+ break;
+ case FILTER_GRADIENTBEVEL:
+ dupBuffered(dupByte()*5 + 19);
+ break;
+ default:
+ tellUser(1, "Unknown filter");
+ }
+}
+
+void writePlaceMCStart(unsigned int clipID)
+{
+ unsigned int oldID = 0;
+ unsigned int typefound;
+ unsigned int flags;
+ unsigned long int length, eventLength;
+
+ /* skip all mcs without onClipEvent actions */
+ do {
+ length = findNextTags(&typefound, 2, TAG_PLACEOBJECT2, TAG_PLACEOBJECT3);
+ if (typefound == TAG_PLACEOBJECT2) {
+ flags = fgetc(updateFile);
+ if (flags & PF_ONCLIPEVENTS)
+ break;
+ writeTagHeader(TAG_PLACEOBJECT2, length);
+ flput(flags);
+ /* copy the rest of the placeobject2 */
+ dupBuffered(length - 1);
+ }
+ else {
+ flags = getWord(updateFile);
+ if (flags & PF_ONCLIPEVENTS)
+ break;
+ writeTagHeader(TAG_PLACEOBJECT3, length);
+ flputShort(flags);
+ /* copy the rest of the placeobject3 */
+ dupBuffered(length - 2);
+ }
+ } while (1);
+
+ /* placemc header, temporary long length, save length pos */
+ writeTagHeader(typefound, 0xFF);
+ placeMCLengthPos = ftell(tempFile) - 4;
+
+ if (typefound == TAG_PLACEOBJECT3)
+ flputShort(flags);
+ else
+ flput(flags);
+
+ /* character depth */
+ dupWord();
+
+ if (flags & PF_CHARACTER)
+ oldID = dupWord();
+ else
+ tellUser(1, "Couldn't update because of unexpected SWF structure:\nold placeMovieClip ID missing, new ID %u", clipID);
+ if (oldID != clipID)
+ tellUser(1, "Couldn't update because of unexpected SWF structure:\nold placeMovieClip ID %u doesn't match new ID %u", oldID, clipID);
+
+ if (flags & PF_MATRIX)
+ dupMatrix();
+ if (flags & PF_COLORTRANSFORM)
+ dupColorTransform();
+ if (flags & PF_RATIO)
+ dupWord();
+ if (flags & PF_NAME)
+ while (dupByte() != 0);
+ if (flags & PF_DEFINECLIP)
+ dupWord();
+ if (flags & PF_FILTERS)
+ dupFilters();
+ if (flags & PF_BLENDMODE)
+ dupByte();
+ if (flags & PF_BITMAPCACHING)
+ dupByte();
+
+ /* reserved: always 0 */
+ dupWord();
+
+ /* save the pos for logical or of all events */
+ MCAllEventsPos = ftell(tempFile);
+
+ /* skip old events */
+ if (swfVersion == 5) {
+ /* dup logical or of all events - temporary */
+ dupWord();
+ while (getWord(updateFile) > 0) {
+ eventLength = getDoubleWord(updateFile);
+ skipProtected(updateFile, eventLength);
+ }
+ }
+ else if (swfVersion >= 6) {
+ /* dup logical or of all events - temporary */
+ dupLong();
+ while (getDoubleWord(updateFile) > 0) {
+ eventLength = getDoubleWord(updateFile);
+ skipProtected(updateFile, eventLength);
+ }
+ }
+}
+
+void writePlaceMCEnd(unsigned long int flags)
+{
+ /* write empty event */
+ flputShort(0);
+ if (swfVersion >= 6)
+ flputShort(0);
+
+ updateTmpLength(placeMCLengthPos, ftell(tempFile) - placeMCLengthPos - 4);
+
+ if (swfVersion == 5)
+ updateShort(MCAllEventsPos, (unsigned int) flags);
+ else if (swfVersion >= 6) {
+ updateShort(MCAllEventsPos, (unsigned int) (flags & 0xFFFF));
+ updateShort(MCAllEventsPos + 2, (unsigned int) ((flags >> 16) & 0xFFFF));
+ }
+
+ placeMCLengthPos = 0;
+ MCAllEventsPos = 0;
+}
+
+void writeOnClipEvent(unsigned long int flag)
+{
+ /* write event flag */
+ flputShort(flag);
+ if (swfVersion >= 6)
+ flputShort((unsigned int) (flag >> 16));
+
+ /* write action length */
+ flputLong(len);
+
+ flushOutput();
+}
+
+void writeButtonStart(unsigned int buttonID)
+{
+ int trackAsMenu;
+ unsigned int oldID, actionOffset;
+ unsigned long int length;
+
+ /* skip all buttons without actions */
+ do {
+ length = findNextTag(TAG_DEFINEBUTTON2);
+ oldID = getWord(updateFile);
+ trackAsMenu = fgetc(updateFile);
+ actionOffset = getWord(updateFile);
+
+ if (actionOffset > 0)
+ break;
+
+ writeTagHeader(TAG_DEFINEBUTTON2, length);
+ flputShort(oldID);
+ flput(trackAsMenu);
+ /* put action offset = 0 */
+ flputShort(0);
+ /* copy the rest of the button */
+ dupBuffered(length - 5);
+ } while(1);
+
+ if (oldID != buttonID)
+ tellUser(1, "Couldn't update because of unexpected SWF structure:\nold defineButton ID %u doesn't match new ID %u", oldID, buttonID);
+
+ /* defineButton2 header, temporary long length, save length pos */
+ writeTagHeader(TAG_DEFINEBUTTON2, 0xFF);
+ buttonLengthPos = ftell(tempFile) - 4;
+
+ flputShort(oldID);
+ flput(trackAsMenu);
+ flputShort(actionOffset);
+
+ /* copy button visual part */
+ dupBuffered(actionOffset - 2);
+
+ /* skip old button actions part */
+ skipProtected(updateFile, length - 3 - actionOffset);
+}
+
+void writeButtonEnd(void)
+{
+ updateTmpLength(buttonLengthPos, ftell(tempFile) - buttonLengthPos - 4);
+
+ /* last offset is always 0 */
+ updateShort(buttonLastOffsetPos, 0);
+
+ buttonLengthPos = 0;
+ buttonLastOffsetPos = 0;
+}
+
+void writeButtonEvent(unsigned int flags)
+{
+ /* write offset to the next condition */
+ buttonLastOffsetPos = ftell(tempFile);
+ flputShort(len+4);
+
+ /* write button event flags */
+ flputShort(flags);
+ flushOutput();
+}
+
+void writeDefineMCStart(unsigned int clipID)
+{
+ unsigned int oldID;
+
+ findNextTag(TAG_DEFINEMOVIECLIP);
+
+ /* defineMovieClip header, temporary long length, save length pos */
+ writeTagHeader(TAG_DEFINEMOVIECLIP, 0xFF);
+ defineMCLengthPos = ftell(tempFile) - 4;
+
+ oldID = dupWord();
+ if (oldID != clipID)
+ tellUser(1, "Couldn't update because of unexpected SWF structure:\nold defineMovieClip ID %u doesn't match new ID %u", oldID, clipID);
+
+ /* frames total */
+ dupWord();
+}
+
+void writeDefineMCEnd(void)
+{
+ /* dump the rest of movie clip */
+ findNextTag(TAG_END);
+
+ /* write movie clip end tag */
+ flputShort(0);
+
+ updateTmpLength(defineMCLengthPos, ftell(tempFile) - defineMCLengthPos - 4);
+
+ defineMCLengthPos = 0;
+}
+
+void writeScriptLimits(unsigned int recursion, unsigned int timeout)
+{
+ writeTagHeader(TAG_SCRIPTLIMITS, 4);
+ flputShort(recursion);
+ flputShort(timeout);
+}
+
+void writeProtect(char *str)
+{
+ if (strlen(str) == 0) {
+ /* no password */
+ writeTagHeader(TAG_PROTECT, 0);
+ }
+ else {
+ /* password found */
+ writeTagHeader(TAG_PROTECT, strlen(str) + 3);
+ flputShort(0);
+ flputString(str);
+ }
+}
+
+void writeEnableDebugger(char *str)
+{
+ if (strlen(str) == 0) {
+ /* no password, probably impossible? */
+ writeTagHeader(TAG_ENABLEDEBUGGER, 0);
+ }
+ else {
+ /* password found */
+ writeTagHeader(TAG_ENABLEDEBUGGER, strlen(str) + 3);
+ flputShort(0);
+ flputString(str);
+ }
+}
+
+void writeEnableDebugger2(char *str)
+{
+ if (strlen(str) == 0) {
+ /* no password, probably impossible? */
+ writeTagHeader(TAG_ENABLEDEBUGGER2, 0);
+ }
+ else {
+ /* password found */
+ writeTagHeader(TAG_ENABLEDEBUGGER2, strlen(str) + 3);
+ flputShort(0);
+ flputString(str);
+ }
+}
+
+void writeMetadata(char *str)
+{
+ writeTagHeader(TAG_METADATA, strlen(str) + 1);
+ flputString(str);
+}
+
+void writeFileAttrs(unsigned long int attrs)
+{
+ writeTagHeader(TAG_FILEATTRIBUTES, 4);
+ flputLong(attrs);
+}
+
+void writeImportAssets(char *from, unsigned int numAssets)
+{
+ if (numAssets>0) {
+ unsigned int typefound;
+ skipProtected(updateFile, findNextTags(&typefound, 2, TAG_IMPORTASSETS, TAG_IMPORTASSETS2));
+ if (typefound == TAG_IMPORTASSETS) {
+ writeTagHeader(TAG_IMPORTASSETS, len + strlen(from) + 3);
+ flputString(from);
+ flputShort(numAssets);
+ }
+ else {
+ writeTagHeader(TAG_IMPORTASSETS2, len + strlen(from) + 5);
+ flputString(from);
+ flputShort(numAssets);
+ /* what's this? always 1 ? */
+ flputShort(1);
+ }
+ if (fwrite(output, 1, (size_t) len, tempFile) != (size_t) len)
+ tellUser(1, "Error writing importAssets");
+ flength += len;
+ }
+ len = 0;
+}
+
+void writeExportAssets(unsigned int numAssets)
+{
+ if (numAssets>0) {
+ skipProtected(updateFile, findNextTag(TAG_EXPORTASSETS));
+ writeTagHeader(TAG_EXPORTASSETS, len+2);
+ flputShort(numAssets);
+
+ if (fwrite(output, 1, (size_t) len, tempFile) != (size_t) len)
+ tellUser(1, "Error writing exportAssets");
+
+ flength += len;
+ }
+ len = 0;
+}
+
+static void finalizeTemporaryFile(char *name)
+{
+ fclose(tempFile);
+ if (!backupCreated) {
+ backupName = mstrdup(name);
+ backupCreated = 1;
+ strcpy(backupName + strlen(backupName) - 4, ".$wf");
+ /* remove evtl. existing previous backup foo.$wf */
+ remove(backupName);
+ /* foo.swf -> foo.$wf */
+ if (rename(name, backupName) != 0)
+ tellUser(1, "couldn't update: file %s is in use", name);
+ /* foo.tmp (assemble) or flasm.tmp (compress/decompress) -> foo.swf */
+ rename(tempName, name);
+ }
+ else {
+ /* backup already here, just make temp file our final file */
+ if (remove(name) != 0)
+ tellUser(1, "couldn't update: file %s is in use", name);
+ rename(tempName, name);
+ }
+}
+
+static void getSWFHeader(FILE * f)
+{
+ fread(swfHeader, 1, 3, f);
+ swfHeader[3] = '\0';
+}
+
+void startUpdate(char *outputName)
+{
+ int b, i, bitstotal;
+
+ if ((updateFile = fopen(outputName, "rb")) == NULL)
+ tellUser(1, "Couldn't open file %s for update", outputName);
+
+ getSWFHeader(updateFile);
+
+ if (strcmp(swfHeader, "FWS") != 0) {
+ if (strcmp(swfHeader, "CWS") == 0) {
+ /* decompresses foo.swf, foo.$wf backup is created */
+ decompressSWF(updateFile, outputName);
+ updateFile = fopen(outputName, "rb");
+ /* now we are just after the header in decompressed file */
+ getSWFHeader(updateFile);
+ }
+ else
+ tellUser(1, "Input file %s doesn't appear to be an SWF file", outputName);
+ }
+
+ flength = 0;
+
+ updateName = mstrdup(outputName);
+ tempName = mstrdup(outputName);
+ strcpy(tempName + strlen(tempName) - 4, ".tmp");
+
+ if ((tempFile = fopen(tempName, "wb")) == NULL)
+ tellUser(1, "Couldn't create temporary file");
+
+ /* SWF header */
+ flput('F');
+ flput('W');
+ flput('S');
+
+ /* version */
+ flput(swfVersion = fgetc(updateFile));
+
+ /* file length - temporary! */
+ flput(fgetc(updateFile));
+ flput(fgetc(updateFile));
+ flput(fgetc(updateFile));
+ flput(fgetc(updateFile));
+
+ /* movie bounds */
+ b = fgetc(updateFile);
+ bitstotal = 5 + 4 * ((b & 0xf8) >> 3);
+ flput(b);
+ for (i = 0; i < (bitstotal + 7) / 8 - 1; ++i)
+ flput(fgetc(updateFile));
+
+ /* frame rate and # of frames */
+ flput(fgetc(updateFile));
+ flput(fgetc(updateFile));
+ flput(fgetc(updateFile));
+ flput(fgetc(updateFile));
+}
+
+void finishUpdate(void)
+{
+ /* dump the rest of SWF */
+ findNextTag(0);
+ /* write movie end */
+ flputShort(0);
+
+ updateTmpLength(4, flength);
+
+ fclose(updateFile);
+
+ finalizeTemporaryFile(updateName);
+
+ if (compressAfter) {
+ updateFile = fopen(updateName, "rb");
+ getSWFHeader(updateFile);
+ compressSWF(updateFile, updateName);
+ }
+
+ if (mode == MODE_UPDATE)
+ tellUser(0, "%s successfully updated, %li bytes", updateName, flength);
+ else if (mode == MODE_ASSEMBLE)
+ tellUser(0, "%s successfully assembled to %s, %li bytes", inputName, updateName, flength);
+}
+
+void writeASBytecode(void)
+{
+ long int n = 0;
+ patchTargets();
+
+ if (nLabels > 0) {
+ nLabels = 0;
+ free(labels);
+ labels = NULL;
+ }
+
+ if (boutput == 0) {
+ printf("%s", "__bytecode__(\"");
+ while(n++ < len)
+ printf("%02x", *(output+n-1));
+ printf("%s", "\");\n");
+ }
+ else
+ fwrite(output, 1, len, stdout);
+}
+
+static void createTemporaryFile(void)
+{
+ tempName = mstrdup("flasm.tmp");
+ if ((tempFile = fopen(tempName, "wb+")) == NULL)
+ tellUser(1, "Couldn't create file: %s", tempName);
+}
+
+static void decompressSWF(FILE *f, char *fname)
+{
+ z_stream stream;
+ static byte inputBuffer[MAX_BUFFER], outputBuffer[MAX_BUFFER];
+ int status, count;
+
+ flength = 0;
+ createTemporaryFile();
+
+ /* SWF header */
+ flput('F');
+ flput('W');
+ flput('S');
+
+ /* version */
+ flput(fgetc(f));
+
+ flput(fgetc(f));
+ flput(fgetc(f));
+ flput(fgetc(f));
+ flput(fgetc(f));
+
+ stream.avail_in = 0;
+ stream.next_in = inputBuffer;
+ stream.next_out = outputBuffer;
+ stream.zalloc = (alloc_func) NULL;
+ stream.zfree = (free_func) NULL;
+ stream.opaque = (voidpf) 0;
+ stream.avail_out = MAX_BUFFER;
+
+ status = inflateInit(&stream);
+ if (status != Z_OK)
+ tellUser(0, "Error %i decompressing SWF: %s\n", status, stream.msg);
+
+ do {
+ if (stream.avail_in == 0) {
+ stream.next_in = inputBuffer;
+ stream.avail_in = fread(inputBuffer, 1, MAX_BUFFER, f);
+ }
+
+ if (stream.avail_in == 0)
+ break;
+
+ status = inflate(&stream, Z_SYNC_FLUSH);
+
+ count = MAX_BUFFER - stream.avail_out;
+ if (count) {
+ fwrite(outputBuffer, 1, count, tempFile);
+ flength += count;
+ }
+
+ stream.next_out = outputBuffer;
+ stream.avail_out = MAX_BUFFER;
+ }
+ while (status == Z_OK);
+
+ if (status != Z_STREAM_END && status != Z_OK)
+ tellUser(0, "Error %i decompressing SWF: %s\n", status, stream.msg);
+
+ status = inflateEnd(&stream);
+ if (status != Z_OK)
+ tellUser(0, "Error %i decompressing SWF: %s\n", status, stream.msg);
+
+ fclose(f);
+
+ if (mode != MODE_DISASSEMBLE)
+ finalizeTemporaryFile(fname);
+
+ if (mode == MODE_DECOMPRESS)
+ tellUser(0, "%s successfully decompressed, %li bytes", fname, flength);
+
+ wasCompressed = 1;
+}
+
+static void compressSWF(FILE *f, char *fname)
+{
+ z_stream stream;
+ static byte inputBuffer[MAX_BUFFER], outputBuffer[MAX_BUFFER];
+ int status, count;
+
+ flength = 0;
+ createTemporaryFile();
+
+ /* SWF header */
+ flput('C');
+ flput('W');
+ flput('S');
+
+ /* version */
+ flput(fgetc(f));
+
+ flput(fgetc(f));
+ flput(fgetc(f));
+ flput(fgetc(f));
+ flput(fgetc(f));
+
+ stream.avail_in = 0;
+ stream.next_out = outputBuffer;
+ stream.avail_out = MAX_BUFFER;
+ stream.zalloc = (alloc_func) NULL;
+ stream.zfree = (free_func) NULL;
+ stream.opaque = (voidpf) 0;
+ stream.next_in = inputBuffer;
+
+ status = deflateInit(&stream, Z_BEST_COMPRESSION);
+
+ if (status != Z_OK)
+ tellUser(1, "Error %i compressing SWF: %s\n", status, stream.msg);
+
+ while (1) {
+ if (stream.avail_in == 0) {
+ stream.next_in = inputBuffer;
+ stream.avail_in = fread(inputBuffer, 1, MAX_BUFFER, f);
+ }
+
+ if (stream.avail_in == 0)
+ break;
+
+ status = deflate(&stream, Z_NO_FLUSH);
+ if (status != Z_OK)
+ tellUser(1, "Error %i compressing SWF: %s\n", status, stream.msg);
+
+ count = MAX_BUFFER - stream.avail_out;
+ if (count) {
+ fwrite(outputBuffer, 1, count, tempFile);
+ flength += count;
+ }
+
+ stream.next_out = outputBuffer;
+ stream.avail_out = MAX_BUFFER;
+ }
+
+ stream.next_out = outputBuffer;
+ stream.avail_out = MAX_BUFFER;
+
+ do {
+ status = deflate(&stream, Z_FINISH);
+
+ count = MAX_BUFFER - stream.avail_out;
+ if (count) {
+ fwrite(outputBuffer, 1, count, tempFile);
+ flength += count;
+ }
+
+ stream.next_out = outputBuffer;
+ stream.avail_out = MAX_BUFFER;
+ }
+ while (status == Z_OK);
+
+ if (status != Z_STREAM_END)
+ tellUser(1, "Error %i compressing SWF: %s\n", status, stream.msg);
+
+ status = deflateEnd(&stream);
+ if (status != Z_OK)
+ tellUser(1, "Error %i compressing SWF: %s\n", status, stream.msg);
+
+ fclose(f);
+
+ finalizeTemporaryFile(fname);
+
+ if (mode == MODE_COMPRESS)
+ tellUser(0, "%s successfully compressed, %li bytes", fname, flength);
+
+}
+
+extern int yydebug;
+
+static void usage(void)
+{
+ printf("\nFlasm %s build %s", FLASM_VERSION, __DATE__);
+ // printf(" (zlib %s)", ZLIB_VERSION);
+ puts("");
+ puts("");
+ puts("(c) 2001 Opaque Industries, (c) 2002-2005 Igor Kogan, (c) 2005 Wang Zhen");
+ puts("All rights reserved. See LICENSE.TXT for terms of use.");
+ puts("");
+ puts("Usage: flasm [command] filename");
+ puts("");
+ puts("Commands:");
+ puts(" -d Disassemble SWF file to the console");
+ puts(" -a Assemble Flasm project (FLM)");
+ puts(" -u Update SWF file, replace Flasm macros");
+ puts(" -b Assemble actions to __bytecode__ instruction or byte sequence");
+ puts(" -z Compress SWF with zLib");
+ puts(" -x Decompress SWF");
+ puts("");
+ puts("Backups with $wf extension are created for altered SWF files.");
+ puts("");
+ puts("To save disassembly or __bytecode__ to file, redirect it:");
+ puts("flasm -d foo.swf > foo.flm");
+ puts("flasm -b foo.txt > foo.as");
+ puts("");
+ puts("Read flasm.html for more information.");
+
+ mexit(EXIT_FAILURE);
+}
+
+static void unescapePath(char *argument)
+{
+ int n = 0;
+ char esc[3];
+ char *s = argument;
+
+ inputName = mstrdup(NULL);
+
+ while ((inputName[n] = *s++) != 0) {
+ if ((inputName[n] == '.') && (*s == 'h') && (*(s + 1) == 't') && (*(s + 2) == 'm'))
+ /* extension found */
+ break;
+
+ if (inputName[n] == '%') {
+ /* unescape URL encoded char */
+ esc[0] = *s++;
+ esc[1] = *s++;
+ esc[2] = 0;
+
+ inputName[n] = (char) (xtoi(esc));
+ }
+ n++;
+ }
+
+ inputName[n] = '\0';
+ strcat(inputName, ".swf");
+}
+
+static int readINI(char *exepath, char *names, char *types, ...)
+{
+ /* slightly changed INITVARS from SNIPPETS collection, public domain by Raymond Gardner, Sept. 1991 */
+ FILE *iniFile;
+ char ln[256], *p, *namep, *typep, name[40], *e;
+ va_list arglist;
+ void *argp;
+ int k;
+
+ if ((iniFile = fopen("flasm.ini", "r")) == NULL) {
+ /* flasm.ini not found in current directory, look at executable's path */
+ int pathlen = strlen(exepath);
+ char inipath[pathlen + 10], *inipathptr;
+ if (exepath == NULL || *exepath == '\0')
+ return -1;
+ strcpy(inipath, exepath);
+ inipathptr = inipath + pathlen;
+ while (*inipathptr != '\\' && *inipathptr != '/' && *inipathptr != ':' && inipathptr>=inipath)
+ inipathptr--;
+
+ strcpy(inipathptr + 1, "flasm.ini");
+ if ((iniFile = fopen(inipath, "r")) == NULL)
+ return -1;
+ }
+
+ while (fgets(ln, 256, iniFile)) { /* read ini file */
+ while (isspace(ln[0])) /* drop leading whitespace */
+ memmove(ln, ln + 1, strlen(ln));
+ if (ln[0] == '\0' || ln[0] == '#') /* skip if blank line or comment */
+ continue;
+
+ p = strchr(ln, '='); /* find equal sign */
+ if (p == NULL) /* error if none */
+ tellUser(1, "Error parsing flasm.ini: %s", ln);
+
+ while (p > ln && isspace(p[-1])) { /* remove whitespace before eq sign */
+ memmove(p - 1, p, strlen(p - 1));
+ --p;
+ }
+ *p++ = '\0'; /* plug EOS over eq sign */
+
+ while (isspace(p[0])) /* remove leading space on init string */
+ memmove(p, p + 1, strlen(p));
+
+ k = strlen(p) - 1; /* init string length */
+ if (k < 0)
+ tellUser(1, "Error parsing flasm.ini: %s", ln);
+
+ if (p[k] == '\n')
+ p[k] = '\0'; /* plug EOS over newline */
+ else if (feof(iniFile)) /* '\n' is missing - last line or buffer exceeded? */
+ p[k + 1] = '\0';
+ else
+ tellUser(1, "Line too long in flasm.ini: %s", ln);
+
+ va_start(arglist, types); /* setup for arglist search */
+
+ namep = names; /* init ptr to var names */
+ typep = types; /* init ptr to var types */
+
+ while (*namep == ' ') /* skip blanks before namelist */
+ ++namep;
+
+ while (*typep) { /* while any typelist items left... */
+ argp = (void *) va_arg(arglist, void *); /* get var arg */
+
+ k = strcspn(namep, " "); /* length of namelist entry */
+ memmove(name, namep, k); /* put into name hold area */
+ name[k] = '\0'; /* terminate it */
+ if (strIcmp(name, ln) != 0) { /* if it doesn't match... */
+ namep += k; /* get next name */
+ while (*namep == ' ')
+ ++namep;
+ ++typep; /* get next type */
+ }
+ else { /* else name is found... */
+ if (*typep == 'i') { /* if it's an int, init it */
+ *(int *) argp = atoi(p);
+ }
+ else if (*typep == 's' || *typep == 'p') {
+ if (*p == '"') { /* is string in quotes? */
+ ++p; /* skip leading quote, and */
+ e = strchr(p, '"'); /* look for trailing quote */
+ if (e) /* terminate string if found */
+ *e = '\0';
+ }
+ if (*typep == 'p') /* if it's a char *ptr */
+ *(char **) argp = mstrdup(p);
+ else /* must be char array */
+ strcpy(argp, p); /* copy in string */
+ }
+ else
+ tellUser(1, "Contact developer: bad argument type in readINI() call");
+
+ break; /* break search; get next line */
+ }
+ }
+ va_end(arglist);
+ }
+
+ fclose(iniFile);
+ return 0;
+}
+
+static void parseArgs(int argc, char *argv[])
+{
+ int ini;
+
+ if (argv[1] == NULL)
+ usage();
+
+ ini = readINI(argv[0],
+ "logto flabrowser flaplayer flatest showoffset hexoffset boutput literalconstants literalregisters clearregisterargs logmode",
+ "ppppiiiiiii",
+ &logto, &flabrowser, &flaplayer, &flatest, &showoffset, &hexoffset, &boutput, &literalconstants, &literalregisters, &clearregisterargs, &logmode);
+
+ if (ini != 0)
+ tellUser(0, "Flasm configuration file flasm.ini not found, using default values");
+
+ if ((strstr(argv[1], ".htm") != NULL) || (strstr(argv[1], "http://") != NULL)) {
+ mode = MODE_IDE;
+
+ if ((strIstr(argv[1], "ContextHelp") != NULL) || (strIstr(argv[1], "http://") != NULL)) {
+ /* an attempt to access flash help */
+ mode = MODE_FLASH_HELP;
+
+ if (strlen(flabrowser) == 0)
+ tellUser(1, "You must define 'flabrowser' value in flasm.ini to access flash help");
+
+ if (access(flabrowser, X_OK) != 0)
+ tellUser(1, "Couldn't start browser: %s", flabrowser);
+
+ strcpy(flapath, flabrowser);
+ strcat(flapath, " ");
+ strcat(flapath, argv[1]);
+ return;
+ }
+
+ if (strIstr(flatest, "FLAPLAYER") != NULL)
+ strcpy(flapath, flaplayer);
+ else if (strIstr(flatest, "FLABROWSER") != NULL)
+ strcpy(flapath, flabrowser);
+ else
+ tellUser(1, "Invalid or missing 'flatest' value in flasm.ini");
+
+ if (strlen(flapath) == 0)
+ tellUser(1, "You must define '%s' value in flasm.ini for debugging", flatest);
+
+ if (access(flapath, X_OK) != 0)
+ tellUser(1, "Couldn't start: %s", flapath);
+
+ if (strstr(argv[1], "file:///") != NULL)
+ /* skip "file:///" (8 chars) */
+ unescapePath(argv[1] + 8);
+ else
+ unescapePath(argv[1]);
+
+ if ((inputFile = fopen(inputName, "rb")) == NULL)
+ tellUser(1, "Couldn't open input file %s for reading", inputName);
+
+ strcat(flapath, " ");
+ strcat(flapath, argv[1]);
+
+ if (strIstr(flatest, "FLAPLAYER") != NULL)
+ strcpy(strstr(flapath, ".htm"), ".swf\0");
+
+ return;
+ }
+
+ if (argv[1][0] == '-') {
+ int i;
+ if (argc < 3)
+ usage();
+ inputName = mstrdup(NULL);
+ strcpy(inputName, argv[2]);
+
+ /* join all arguments into one string - to support spaces in file names */
+ for (i = 3; i < argc; i++) {
+ strcat(inputName, " ");
+ strcat(inputName, argv[i]);
+ }
+
+ switch (argv[1][1]) {
+ case 'd':
+ mode = MODE_DISASSEMBLE;
+ break;
+
+ case 'a':
+ mode = MODE_ASSEMBLE;
+ break;
+
+ case 'u':
+ mode = MODE_UPDATE;
+ break;
+
+ case 'b':
+ mode = MODE_ASBYTECODE;
+ break;
+
+ case 'x':
+ mode = MODE_DECOMPRESS;
+ break;
+
+ case 'z':
+ mode = MODE_COMPRESS;
+ break;
+
+ default:
+ usage();
+ }
+ }
+ else {
+ int i;
+ inputName = mstrdup(NULL);
+ strcpy(inputName, argv[1]);
+
+ /* join all arguments into one string - to support spaces in file names */
+ for (i = 2; i < argc; i++) {
+ strcat(inputName, " ");
+ strcat(inputName, argv[i]);
+ }
+
+ if (strIstr(inputName, ".swf") != NULL) {
+ flmName = mstrdup(inputName);
+ strcpy(strIstr(flmName, ".swf"), ".flm");
+ /* redirect stdout to inputName.flm; should close it later? */
+ if (freopen(flmName, "wb", stdout) == NULL)
+ tellUser(1, "Couldn't open output file %s for writing", flmName);
+
+ mode = MODE_DISASSEMBLE;
+ }
+ else if (strIstr(inputName, ".flm") != NULL) {
+ mode = MODE_ASSEMBLE;
+ }
+ else
+ usage();
+ }
+
+ if (inputName == NULL)
+ usage();
+
+ if ((inputFile = fopen(inputName, "rb")) == NULL)
+ tellUser(1, "Couldn't open input file %s for reading", inputName);
+}
+
+int main(int argc, char *argv[])
+{
+ yydebug = 0;
+
+#ifdef MEMWATCH
+ mwStatistics(2);
+#endif
+
+ checkByteOrder();
+
+ parseArgs(argc, argv);
+
+ if (mode == MODE_DISASSEMBLE) {
+ getSWFHeader(inputFile);
+ if (strcmp(swfHeader, "FWS") != 0) {
+ if (strcmp(swfHeader, "CWS") == 0) {
+ decompressSWF(inputFile, inputName);
+ /* skip SWF header, we know it's 'FWS' */
+ fseek(tempFile, 3, SEEK_SET);
+ disassembleSWF(tempFile, inputName);
+ remove(tempName);
+ }
+ else
+ tellUser(1, "Input file doesn't appear to be an SWF file..");
+ }
+ else
+ disassembleSWF(inputFile, inputName);
+
+ mexit(EXIT_SUCCESS);
+ }
+
+ if (mode == MODE_DECOMPRESS) {
+ getSWFHeader(inputFile);
+ if (strcmp(swfHeader, "CWS") != 0) {
+ if (strcmp(swfHeader, "FWS") == 0)
+ tellUser(1, "Know what, the SWF isn't compressed");
+ else
+ tellUser(1, "Input file doesn't appear to be an SWF file..");
+ }
+ decompressSWF(inputFile, inputName);
+ mexit(EXIT_SUCCESS);
+ }
+
+ if (mode == MODE_COMPRESS) {
+ getSWFHeader(inputFile);
+ if (strcmp(swfHeader, "FWS") != 0) {
+ if (strcmp(swfHeader, "CWS") == 0)
+ tellUser(1, "Know what, the SWF is already compressed");
+ else
+ tellUser(1, "Input file doesn't appear to be an SWF file..");
+ }
+ compressSWF(inputFile, inputName);
+ mexit(EXIT_SUCCESS);
+ }
+
+ if (mode == MODE_ASSEMBLE || mode == MODE_ASBYTECODE) {
+ yyin = inputFile;
+ yyparse();
+ fclose(inputFile);
+ mexit(EXIT_SUCCESS);
+ }
+
+ if ((mode >= MODE_UPDATE) && (mode != MODE_FLASH_HELP)) {
+ FILE *stdoutTempFile;
+ getSWFHeader(inputFile);
+
+ /* overwrite user settings */
+ showoffset = 0;
+ literalconstants = 1;
+ literalregisters = 0;
+
+ if (strcmp(swfHeader, "FWS") != 0) {
+ if (strcmp(swfHeader, "CWS") == 0) {
+ decompressSWF(inputFile, inputName);
+ inputFile = fopen(inputName, "rb");
+ getSWFHeader(inputFile);
+ }
+ else
+ tellUser(1, "Input file doesn't appear to be an SWF file..");
+ }
+
+ flmName = mstrdup(inputName);
+ strcpy(strIstr(flmName, ".swf"), ".$lm");
+
+ /* redirect stdout to inputName.flm */
+ stdoutTempFile = freopen(flmName, "wb", stdout);
+
+ if (stdoutTempFile == NULL)
+ tellUser(1, "Couldn't create temporary file");
+
+ disassembleSWF(inputFile, inputName);
+ fclose(stdoutTempFile);
+
+ inputFile = fopen(flmName, "rb");
+ inputName = mstrdup(flmName);
+ yyin = inputFile;
+ yyparse();
+
+ fclose(inputFile);
+ remove(flmName);
+ }
+
+ if (mode >= MODE_IDE) {
+ if (system(flapath) == -1)
+ tellUser(1, "Couldn't execute: %s", flapath);
+ }
+
+ mexit(EXIT_SUCCESS);
+ /* to make compiler happy */
+ exit(0);
+}
+
+/* indent -l200 --ignore-newlines -bap -nbc -fc1 -npsl -sob -ncdb -brs -br -nce -cdw -npcs -i4 -ts4 -c60 -cd30 -cli4 -cbi4 -bs -nss flasm.c */
+/* splint -retvalint +posixlib -boolops -retvalother -realcompare -predboolint unflasm.c flasm.c util.c assembler.tab.c > flasm.lint */
More information about the pkg-flash-devel
mailing list