📄 compile.c
字号:
/* Ming, an SWF output library Copyright (C) 2002 Opaque Industries - http://www.opaque.net/ This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*/#ifndef WIN32 #include <unistd.h>#endif#include <stdio.h>#include <stdlib.h>#include <ctype.h>#include <string.h>#include "libming.h"#include "compile.h"#include "actiontypes.h"#include "blocks/error.h"/* Define this to have some debugging output when outputting DEFINEFUNCTION2 */#undef MING_DEBUG_FUNCTION2// XXX: set by swf[4|5]Init()int swfVersion = 0;static int nConstants = {0}, maxConstants = {0}, sizeConstants = {0};static char **constants = NULL;char *stringConcat(char *a, char *b){ if ( a != NULL ) { if ( b != NULL ) { a = (char*)realloc(a, strlen(a)+strlen(b)+1); if(a == NULL) return NULL; strcat(a, b); free(b); } return a; } else return b;}void bufferPatchLength(Buffer buffer, int back){ unsigned char *output = buffer->buffer; int len = bufferLength(buffer); output[len-back-1] = (back>>8) & 0xff; output[len-back-2] = back & 0xff;}/* add len more bytes to length of the pushdata opcode pointed to by buffer->pushloc */void bufferPatchPushLength(Buffer buffer, int len){ int oldsize; if(buffer->pushloc != NULL) { oldsize = (buffer->pushloc[0] & 0xff) | ((buffer->pushloc[1] & 0xff) << 8); oldsize += len; buffer->pushloc[0] = oldsize & 0xff; buffer->pushloc[1] = (oldsize >> 8) & 0xff; } else SWF_error("problem with bufferPatchPushLength\n");}static int useConstants = 1;void Ming_useConstants(int flag){ useConstants = flag;}int addConstant(const char *s){ int i; for(i=0; i<nConstants; ++i) { if(strcmp(s, constants[i]) == 0) return i; } /* Don't let constant pool biggern then allowed */ if ( sizeConstants+strlen(s)+1 > MAXCONSTANTPOOLSIZE ) return -1; if(nConstants == maxConstants) constants = (char **) realloc(constants, (maxConstants += 64) * sizeof(char *)); constants[nConstants] = strdup(s); sizeConstants += (strlen(s)+1); return nConstants++;}int bufferWriteConstants(Buffer out){ int i, len=2; if(nConstants == 0) return 0; bufferWriteU8(out, SWFACTION_CONSTANTPOOL); bufferWriteS16(out, 0); /* length */ bufferWriteS16(out, nConstants); for(i=0; i<nConstants; ++i) { len += bufferWriteHardString(out, constants[i], strlen(constants[i])+1); free(constants[i]); } nConstants = 0; sizeConstants = 0; bufferPatchLength(out, len); return len+3;}Buffer newBuffer(){ Buffer out = (Buffer)malloc(BUFFER_SIZE); if(out == NULL) return NULL; memset(out, 0, BUFFER_SIZE); out->buffer = (byte*)malloc(BUFFER_INCREMENT); out->pos = out->buffer; *(out->pos) = 0; out->buffersize = out->free = BUFFER_INCREMENT; out->pushloc = NULL; out->hasObject = 0; return out;}void destroyBuffer(Buffer out){ free(out->buffer); free(out);}int bufferLength(Buffer out){ if(out) return (out->pos)-(out->buffer); else return 0;}/* make sure there's enough space for bytes bytes */void bufferCheckSize(Buffer out, int bytes){ if(bytes > out->free) { int New = BUFFER_INCREMENT * ((bytes-out->free-1)/BUFFER_INCREMENT + 1); int num = bufferLength(out); /* in case buffer gets displaced.. */ unsigned char *newbuf = (unsigned char*)realloc(out->buffer, out->buffersize+New); if(newbuf != out->buffer) { int pushd = 0; if(out->pushloc) pushd = out->pos - out->pushloc; out->pos = newbuf+num; if(out->pushloc) out->pushloc = out->pos - pushd; } out->buffer = newbuf; out->buffersize += New; out->free += New; }}int bufferWriteData(Buffer b, const byte *data, int length){ int i; bufferCheckSize(b, length); for(i=0; i<length; ++i) bufferWriteU8(b, data[i]); return length;}int bufferWriteBuffer(Buffer a, Buffer b){ if(!a) return 0; if(b) return bufferWriteData(a, b->buffer, bufferLength(b)); return 0;}/* if a's last op and b's first op are both PUSH, concat into one op */int bufferWriteDataAndPush(Buffer a, Buffer b){ int i, pushd = 0; byte *data = b->buffer; int length = b->pos - b->buffer; if(a->pushloc && (b->buffer[0] == SWFACTION_PUSH) && swfVersion > 4) { pushd = (b->buffer[1] & 0xff) | ((b->buffer[2] & 0xff) << 8); bufferPatchPushLength(a, pushd); data += 3; length -= 3; } if(b->pushloc) pushd = b->pos - b->pushloc; bufferCheckSize(a, length); for(i=0; i<length; ++i) bufferWriteU8(a, data[i]); if(a->pushloc && (b->buffer[0] == SWFACTION_PUSH) && (b->pushloc == b->buffer+1)) ; /* b is just one pushdata, so do nothing.. */ else if(b->pushloc) a->pushloc = a->pos - pushd; else a->pushloc = 0; return length;}int bufferConcatSimple(Buffer a, Buffer b){ int len = 0; if(!a) return 0; if(b) { len = bufferWriteBuffer(a, b); destroyBuffer(b); } return len;}int bufferConcat(Buffer a, Buffer b){ int len = 0; if(!a) return 0; if(b) { len = bufferWriteDataAndPush(a, b); destroyBuffer(b); } return len;}int bufferWriteOp(Buffer out, int data){ bufferWriteU8(out, data); out->pushloc = NULL; return 1;}int bufferWritePushOp(Buffer out){ bufferWriteU8(out, SWFACTION_PUSH); out->pushloc = out->pos; return 1;}int bufferWriteU8(Buffer out, int data){ bufferCheckSize(out, 1); *(out->pos) = data; out->pos++; out->free--; return 1;}int bufferWriteS16(Buffer out, int data){ if(data < 0) data = (1<<16)+data; bufferWriteU8(out, data%256); data >>= 8; bufferWriteU8(out, data%256); return 2;}int bufferWriteHardString(Buffer out, const char *string, int length){ int i; for(i=0; i<length; ++i) bufferWriteU8(out, (byte)string[i]); return length;}int bufferWriteConstantString(Buffer out, const char *string, int length){ int n; if(swfVersion < 5) return -1; if(useConstants) n = addConstant((char*) string); else n = -1; if(n == -1) { bufferWriteU8(out, PUSH_STRING); return bufferWriteHardString(out, string, length) + 1; } else if(n < 256) { bufferWriteU8(out, PUSH_CONSTANT); return bufferWriteU8(out, n) + 1; } else { bufferWriteU8(out, PUSH_CONSTANT16); return bufferWriteS16(out, n) + 1; }}/* allow pushing STRINGs for SWF>=5 */int bufferWritePushString(Buffer out, char *string, int length){ int l, len = 0; if(out->pushloc == NULL || swfVersion < 5) { len = 3; bufferWritePushOp(out); bufferWriteS16(out, length+1); } bufferWriteU8(out, PUSH_STRING); l = bufferWriteHardString(out, string, length); bufferPatchPushLength(out, l + 1); return len + l + 1;}int bufferWriteString(Buffer out, const char *string, int length){ if(swfVersion < 5) { bufferWritePushOp(out); bufferWriteS16(out, length+1); bufferWriteU8(out, PUSH_STRING); bufferWriteHardString(out, string, length); return 4 + length; } else { int l; if(out->pushloc == NULL) { bufferWritePushOp(out); bufferWriteS16(out, 0); } l = bufferWriteConstantString(out, string, length); bufferPatchPushLength(out, l); return l; }}int bufferWriteInt(Buffer out, int i){ int len = 0; unsigned char *p = (unsigned char *)&i; if(out->pushloc == NULL || swfVersion < 5) { len = 3; bufferWritePushOp(out); bufferWriteS16(out, 5); } else bufferPatchPushLength(out, 5); bufferWriteU8(out, PUSH_INT);#if SWF_LITTLE_ENDIAN bufferWriteU8(out, p[0]); bufferWriteU8(out, p[1]); bufferWriteU8(out, p[2]); bufferWriteU8(out, p[3]);#else bufferWriteU8(out, p[3]); bufferWriteU8(out, p[2]); bufferWriteU8(out, p[1]); bufferWriteU8(out, p[0]);#endif return len + 5;}int bufferWriteFloat(Buffer out, float f){ int len = 0; unsigned char *p = (unsigned char *)&f; if(out->pushloc == NULL || swfVersion < 5) { len = 3; bufferWritePushOp(out); bufferWriteS16(out, 5); } else bufferPatchPushLength(out, 5); bufferWriteU8(out, PUSH_FLOAT);#if SWF_LITTLE_ENDIAN bufferWriteU8(out, p[0]); bufferWriteU8(out, p[1]); bufferWriteU8(out, p[2]); bufferWriteU8(out, p[3]); #else bufferWriteU8(out, p[3]); bufferWriteU8(out, p[2]); bufferWriteU8(out, p[1]); bufferWriteU8(out, p[0]);#endif return len + 5;}int bufferWriteDouble(Buffer out, double d){ int len = 0; unsigned char *p = (unsigned char *)&d; if(out->pushloc == NULL || swfVersion < 5) { len = 3; bufferWritePushOp(out); bufferWriteS16(out, 9); } else bufferPatchPushLength(out, 5); bufferWriteU8(out, PUSH_DOUBLE);#if SWF_LITTLE_ENDIAN bufferWriteU8(out, p[4]); bufferWriteU8(out, p[5]); bufferWriteU8(out, p[6]); bufferWriteU8(out, p[7]); bufferWriteU8(out, p[0]); bufferWriteU8(out, p[1]); bufferWriteU8(out, p[2]); bufferWriteU8(out, p[3]);#else bufferWriteU8(out, p[3]); bufferWriteU8(out, p[2]); bufferWriteU8(out, p[1]); bufferWriteU8(out, p[0]); bufferWriteU8(out, p[7]); bufferWriteU8(out, p[6]); bufferWriteU8(out, p[5]); bufferWriteU8(out, p[4]);#endif return len + 9;}int bufferWriteNull(Buffer out){ int len = 0; if(out->pushloc == NULL || swfVersion < 5) { len = 3; bufferWritePushOp(out); bufferWriteS16(out, 1); } else bufferPatchPushLength(out, 1); bufferWriteU8(out, PUSH_NULL); return len + 1;}int bufferWriteUndef(Buffer out){ int len = 0; if(out->pushloc == NULL || swfVersion < 5) { len = 3; bufferWritePushOp(out); bufferWriteS16(out, 1); } else bufferPatchPushLength(out, 1); bufferWriteU8(out, PUSH_UNDEF); return len + 1;}int bufferWriteBoolean(Buffer out, int val){ int len = 0; if(out->pushloc == NULL || swfVersion < 5) { len = 3; bufferWritePushOp(out); bufferWriteS16(out, 2); } else bufferPatchPushLength(out, 2); bufferWriteU8(out, PUSH_BOOLEAN); bufferWriteU8(out, val ? 1 : 0); return len + 2;}int bufferWriteRegister(Buffer out, int num){ int len = 0; if(out->pushloc == NULL || swfVersion < 5) { len = 3; bufferWritePushOp(out); bufferWriteS16(out, 2); } else bufferPatchPushLength(out, 2); bufferWriteU8(out, PUSH_REGISTER); bufferWriteU8(out, num); return len + 2;}int bufferWriteSetRegister(Buffer out, int num){ bufferWriteU8(out, SWFACTION_STOREREGISTER);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -