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:57 UTC 2006


Author: pabs-guest
Date: Fri Jun  2 09:04:52 2006
New Revision: 7

URL: http://svn.debian.org/wsvn/pkg-flash/?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/pkg-flash/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 *) &num;
+
+	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 *) &num;
+
+	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 *) &num;
+
+	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