📄 compile.c
字号:
bufferWriteS16(out, 1); bufferWriteU8(out, num); return 4;}void lower(char *s){ while(*s) { *s = tolower(*s); ++s; }}/* this code will eventually help to pop extra values off the stack and make sure that continue and break address the proper context */static enum ctx *ctx_stack = {0};static int ctx_count = {0}, ctx_len = {0};void addctx(enum ctx val){ if(ctx_count >= ctx_len) ctx_stack = (enum ctx*) realloc(ctx_stack, (ctx_len += 10) * sizeof(enum ctx)); ctx_stack[ctx_count++] = val;}void delctx(enum ctx val){ if(ctx_count <= 0) SWF_error("consistency check in delctx: stack empty!\n"); else if (ctx_stack[--ctx_count] != val) SWF_error("consistency check in delctx: val %i != %i\n", ctx_stack[ctx_count], val);}int chkctx(enum ctx val){ int n, ret = 0; switch(val) { case CTX_FUNCTION: for(n = ctx_count ; --n >= 0 ; ) switch(ctx_stack[n]) { case CTX_SWITCH: case CTX_FOR_IN: ret++; break; case CTX_FUNCTION: return ret; default: ; /* computers are stupid */ } return -1; case CTX_BREAK: for(n = ctx_count ; --n >= 0 ; ) switch(ctx_stack[n]) { case CTX_SWITCH: return CTX_SWITCH; case CTX_LOOP: return CTX_LOOP; case CTX_FOR_IN: return CTX_FOR_IN; case CTX_FUNCTION: return -1; case CTX_BREAK: return CTX_BREAK; default: ; /* computers are stupid */ } return -1; case CTX_CONTINUE: for(n = ctx_count ; --n >= 0 ; ) switch(ctx_stack[n]) { case CTX_LOOP: case CTX_FOR_IN: return 0; case CTX_FUNCTION: return -1; default: ; /* computers are stupid */ } default: return -1;; /* computers are stupid */ }}/* replace MAGIC_CONTINUE_NUMBER and MAGIC_BREAK_NUMBER with jumps to head or tail, respectively *//* jump offset is relative to end of jump instruction *//* I can't believe this actually worked */void bufferResolveJumpsFull(Buffer out, byte *break_ptr, byte *continue_ptr){ byte *p = out->buffer; int l, target; while(p < out->pos) { if(*p & 0x80) /* then it's a multibyte instruction */ { if(*p == SWFACTION_JUMP) { p += 3; /* plus instruction plus two-byte length */ if(*p == MAGIC_CONTINUE_NUMBER_LO && *(p+1) == MAGIC_CONTINUE_NUMBER_HI) { target = continue_ptr - (p+2); *p = target & 0xff; *(p+1) = (target>>8) & 0xff; } else if(*p == MAGIC_BREAK_NUMBER_LO && *(p+1) == MAGIC_BREAK_NUMBER_HI) { target = break_ptr - (p+2); *p = target & 0xff; *(p+1) = (target>>8) & 0xff; } p += 2; } else { ++p; l = *p; ++p; l += *p<<8; ++p; p += l; } } else ++p; }}// handle SWITCH statementvoid bufferResolveSwitch(Buffer buffer, struct switchcases *slp){ struct switchcase *scp; int n, len; unsigned char *output; len = bufferLength(buffer); for(n = 0, scp = slp->list ; n < slp->count ; n++, scp++) { scp->actlen = bufferLength(scp->action); if((n < slp->count-1)) scp->actlen += 5; if(scp->cond) { scp->condlen = bufferLength(scp->cond) + 8; bufferWriteOp(buffer, SWFACTION_PUSHDUP); bufferConcat(buffer, scp->cond); bufferWriteOp(buffer, SWFACTION_EQUALS2); bufferWriteOp(buffer, SWFACTION_LOGICALNOT); bufferWriteOp(buffer, SWFACTION_IF); bufferWriteS16(buffer, 2); bufferWriteS16(buffer, scp->actlen); } else scp->condlen = 0; bufferConcat(buffer, scp->action); bufferWriteOp(buffer, SWFACTION_JUMP); bufferWriteS16(buffer, 2); bufferWriteS16(buffer, scp->isbreak ? MAGIC_BREAK_NUMBER : 0); if(!scp->cond) { slp->count = n+1; break; } } for(n = 0, scp = slp->list ; n < slp->count ; n++, scp++) { len += scp->condlen; output = buffer->buffer + len; if((n < slp->count-1) && !scp->isbreak) { output[scp->actlen-2] = (scp+1)->condlen & 0xff; output[scp->actlen-1] = (scp+1)->condlen >> 8; } len += scp->actlen; }} int lookupProperty(char *string){ lower(string); if(strcmp(string, "_x") == 0) return PROPERTY_X; if(strcmp(string, "_y") == 0) return PROPERTY_Y; if(strcmp(string, "_xscale") == 0) return PROPERTY_XSCALE; if(strcmp(string, "_yscale") == 0) return PROPERTY_YSCALE; if(strcmp(string, "_currentframe") == 0) return PROPERTY_CURRENTFRAME; if(strcmp(string, "_totalframes") == 0) return PROPERTY_TOTALFRAMES; if(strcmp(string, "_alpha") == 0) return PROPERTY_ALPHA; if(strcmp(string, "_visible") == 0) return PROPERTY_VISIBLE; if(strcmp(string, "_width") == 0) return PROPERTY_WIDTH; if(strcmp(string, "_height") == 0) return PROPERTY_HEIGHT; if(strcmp(string, "_rotation") == 0) return PROPERTY_ROTATION; if(strcmp(string, "_target") == 0) return PROPERTY_TARGET; if(strcmp(string, "_framesloaded") == 0) return PROPERTY_FRAMESLOADED; if(strcmp(string, "_name") == 0) return PROPERTY_NAME; if(strcmp(string, "_droptarget") == 0) return PROPERTY_DROPTARGET; if(strcmp(string, "_url") == 0) return PROPERTY_URL; if(strcmp(string, "_highquality") == 0) return PROPERTY_HIGHQUALITY; if(strcmp(string, "_focusrect") == 0) return PROPERTY_FOCUSRECT; if(strcmp(string, "_soundbuftime") == 0) return PROPERTY_SOUNDBUFTIME; if(strcmp(string, "_quality")==0) return PROPERTY_QUALITY; if(strcmp(string, "_xmouse") == 0) return PROPERTY_XMOUSE; if(strcmp(string, "_ymouse") == 0) return PROPERTY_YMOUSE; SWF_error("No such property: %s\n", string); return -1;}int bufferWriteProperty(Buffer out, char *string){ int property = lookupProperty(string); return bufferWriteFloat(out, property);}// XXX: ???int bufferWriteWTHITProperty(Buffer out){ bufferWriteU8(out, SWFACTION_PUSH); bufferWriteS16(out, 5); bufferWriteU8(out, PUSH_FLOAT); bufferWriteS16(out, 0); bufferWriteS16(out, 0x4680); return 8;}/** * @param func_name * Function name, NULL for anonymous functions. * * @param num_regs * Number of registers. * * @param flags * See SWFDefineFunction2Flags enum. */static int bufferWriteDefineFunction2(Buffer out, char *func_name, Buffer args, Buffer code, int flags, int num_regs){ Buffer c; char buf[1024]; int num_args = 0, i; char *p = (char *) args->buffer; size_t taglen; strcpy(buf, ""); // REGISTERPARAM records c = newBuffer(); // TODO: rewrite this function, all these calls to strncat // seem overkill to me for(i = 0; i < bufferLength(args); i++) { if(p[i] == '\0') { bufferWriteU8(c, 0); bufferWriteHardString(c, buf, strlen(buf)+1); strcpy(buf, ""); num_args++; } else { strncat(buf, &p[i], 1); } } bufferWriteOp(out, SWFACTION_DEFINEFUNCTION2); if(func_name == NULL) { taglen = + 1 /* function name (empty) */ + 2 /* arg count (short) */ + 1 /* reg count (byte) */ + 2 /* flags */ + bufferLength(c) /* swf_params */ + 2 /* body size */ ;#ifdef MING_DEBUG_FUNCTION2 printf("adding anonymouse SWF_DEFINEFUNCTION2 nargs=%d flags=%d" " arglen=%d codelen=%d taglen=%d\n", num_args, flags, bufferLength(args), bufferLength(code), taglen);#endif bufferWriteS16(out, taglen); bufferWriteU8(out, 0); /* empty function name */ } else { taglen = 0 + strlen(func_name)+1 /* function name */ + 2 /* arg count (short) */ + 1 /* reg count (byte) */ + 2 /* flags */ + bufferLength(c) /* swf_params */ + 2 /* body size */ ;#ifdef MING_DEBUG_FUNCTION2 printf("adding named SWF_DEFINEFUNCTION2 name=%s nargs=%d flags=%d" " regparamlen=%d arglen=%d codelen=%d taglen=%d\n", func_name, num_args, flags, bufferLength(c), bufferLength(args), bufferLength(code), taglen);#endif bufferWriteS16(out, taglen); bufferWriteHardString(out, func_name, strlen(func_name)+1); } bufferWriteS16(out, num_args); /* number of params */ bufferWriteU8(out, num_regs); /* register count */ bufferWriteS16(out, flags); /* flags */ //bufferWriteS16(out, 0); /* flags */ bufferConcat(out, c); bufferWriteS16(out, bufferLength(code)); /* code size */ bufferConcat(out, code); return taglen;}void destroyASFunction(ASFunction func){ free(func->name); free(func);}int bufferWriteFunction(Buffer out, ASFunction function, int version){ int tagLen; if(version == 2) { tagLen = bufferWriteDefineFunction2(out, function->name, function->params.buffer, function->code, function->flags, 0); } else { tagLen = 5; tagLen += bufferLength(function->params.buffer); if(function->name != NULL) tagLen += strlen(function->name); bufferWriteOp(out, SWFACTION_DEFINEFUNCTION); bufferWriteS16(out, tagLen); if(function->name == NULL) bufferWriteU8(out, 0); /* empty function name */ else bufferWriteHardString(out, function->name, strlen(function->name) +1 ); bufferWriteS16(out, function->params.count); bufferConcat(out, function->params.buffer); bufferWriteS16(out, bufferLength(function->code)); bufferConcat(out, function->code); } destroyASFunction(function); return tagLen;}ASFunction newASFunction(){ ASFunction func; func = (ASFunction) malloc(sizeof(struct function_s)); func->flags = 0; func->code = NULL; func->params.count = 0; func->params.buffer = NULL; func->name = NULL; return func;}void destroyASClass(ASClass clazz){ ASClassMember member; if(clazz->name) free(clazz->name); member = clazz->members; while(member) { ASClassMember _this = member; member = member->next; free(_this); } free(clazz);}ASFunction ASClass_getConstructor(ASClass clazz){ ASClassMember member; member = clazz->members; while(member) { ASFunction func; ASClassMember _this = member; member = member->next; if(_this->type != METHOD) continue; func = _this->element.function; if(!func || !func->name) continue; if(strcmp(func->name, clazz->name) != 0) continue; _this->element.function = NULL; return func; } return newASFunction(); // default empty constructor}static int bufferWriteClassConstructor(Buffer out, ASClass clazz){ int len = 0; ASFunction func; /* class constructor */ len += bufferWriteString(out, "_global", strlen("_global") + 1); len += bufferWriteOp(out, SWFACTION_GETVARIABLE); len += bufferWriteString(out, clazz->name, strlen(clazz->name) + 1); func = ASClass_getConstructor(clazz); if(func->name) { free(func->name); func->name = NULL; } len += bufferWriteFunction(out, func, 1); len += bufferWriteSetRegister(out, 1); len += bufferWriteOp(out, SWFACTION_SETMEMBER); len += bufferWriteRegister(out, 1); len += bufferWriteString(out, "prototype", strlen("prototype") + 1); len += bufferWriteOp(out, SWFACTION_GETMEMBER); len += bufferWriteSetRegister(out, 2); len += bufferWriteOp(out, SWFACTION_POP); return len;}static int bufferWriteClassMethods(Buffer out, ASClass clazz){ ASClassMember member = clazz->members; int len = 0; while(member) { ASFunction func; ASClassMember _this = member; member = member->next; if(_this->type != METHOD) continue; func = _this->element.function; if(!func || !func->name) continue; if(strcmp(func->name, clazz->name) != 0) { SWF_error("only one class constructor allowed\n"); } len += bufferWriteRegister(out, 2); len += bufferWriteString(out, func->name, strlen(func->name) + 1); free(func->name); func->name = NULL; len += bufferWriteFunction(out, func, 1); len += bufferWriteOp(out, SWFACTION_SETMEMBER); _this->element.function = NULL; } return len;}static int bufferWriteClassVariable(Buffer out, ASVariable var){ int len = 0; if(var->initCode != NULL) { len += bufferWriteRegister(out, 2); len += bufferWriteString(out, var->name, strlen(var->name)+1); len += bufferConcat(out, var->initCode); len += bufferWriteOp(out, SWFACTION_SETMEMBER); } free(var->name); free(var); // aka destroyASVariable return len;}static int bufferWriteClassMembers(Buffer out, ASClass clazz){ ASClassMember member = clazz->members; int len = 0; while(member) { ASVariable var; ASClassMember _this = member; member = member->next; if(_this->type != VARIABLE) continue; var = _this->element.var; if(!var) continue; bufferWriteClassVariable(out, var); _this->element.var = NULL; } return len;}int bufferWriteClass(Buffer out, ASClass clazz){ int len = 0; len += bufferWriteClassConstructor(out, clazz); len += bufferWriteClassMembers(out, clazz); len += bufferWriteClassMethods(out, clazz); /* set class properties */ len += bufferWriteInt(out, 1); len += bufferWriteNull(out); len += bufferWriteString(out, "_global", strlen("_global") + 1); len += bufferWriteOp(out, SWFACTION_GETVARIABLE); len += bufferWriteString(out, clazz->name, strlen(clazz->name) + 1); len += bufferWriteOp(out, SWFACTION_GETMEMBER); len += bufferWriteString(out, "prototype", strlen("prototype") + 1); len += bufferWriteOp(out, SWFACTION_GETMEMBER); len += bufferWriteInt(out, 3); len += bufferWriteString(out, "ASSetPropFlags", strlen("ASSetPropFlags") + 1); len += bufferWriteOp(out, SWFACTION_CALLFUNCTION); len += bufferWriteOp(out, SWFACTION_POP); destroyASClass(clazz); return len;}void ASClassMember_append(ASClassMember m0, ASClassMember end){ ASClassMember mb = m0; while(mb->next) mb = mb->next; mb->next = end;}ASClass newASClass(char *name, ASClassMember members){ ASClass clazz; clazz = (ASClass) malloc(sizeof(struct class_s)); clazz->name = name; clazz->members = members; return clazz; }ASClassMember newASClassMember_function(ASFunction func){ ASClassMember member = (ASClassMember) malloc(sizeof(struct class_member_s)); member->element.function = func; member->type = METHOD; member->next = NULL; return member;}ASClassMember newASClassMember_variable(ASVariable var){ ASClassMember member = (ASClassMember) malloc(sizeof(struct class_member_s)); member->element.var = var; member->type = VARIABLE; member->next = NULL; return member;}ASClassMember newASClassMember_buffer(Buffer buf){ ASClassMember member = (ASClassMember) malloc(sizeof(struct class_member_s)); member->element.buffer = buf; member->type = BUFF; member->next = NULL; return member;}ASVariable newASVariable(char *name, Buffer buf){ ASVariable var = (ASVariable) malloc(sizeof(struct variable_s)); var->name = name; var->initCode = buf; return var;}/* * Local variables: * tab-width: 2 * c-basic-offset: 2 * End: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -