static void check_old_style_EOL_var ( VARIABLE_PTR var ) { if (!strcmp("EOL", var->name) && IS_CONSTANT(var)) { var->type &= ~FFV_DATA_TYPES; var->type |= FFV_EOL; } }
int luaU_guess_locals(Proto* f, int main) { int blockend[255]; int block; int regassign[MAXARG_A]; int regusage[MAXARG_A]; int regblock[MAXARG_A]; int lastfree; int i,i2,x,y,pc; llist list_begin; llist* list_next = &list_begin; if (f->lineinfo != NULL) { return 0; } if (f->sizelocvars>0) { return 0; } list_begin.next = NULL; block = 0; lastfree = 0; blockend[block] = f->sizecode-1; for (i=0; i<f->maxstacksize; i++) { regassign[i] = 0; regusage[i] = 0; regblock[i] = 0; } // parameters, varargs, nil optimizations for (i = 0; i < f->numparams; i++) { list_next = add(list_next,0,blockend[block]); regassign[lastfree] = 0; regusage[lastfree] = 1; regblock[lastfree] = blockend[block]; lastfree++; } if ((f->is_vararg==7) || ((f->is_vararg&2))) { if (main!=0) { list_next = add(list_next,0,blockend[block]); lastfree++; regassign[lastfree] = 0; regusage[lastfree] = 1; regblock[lastfree] = blockend[block]; lastfree++; } } { Instruction i = f->code[0]; OpCode o = GET_OPCODE(i); int a = GETARG_A(i); if ((o == OP_SETGLOBAL) || (o == OP_SETUPVAL)) { int ixx; for (ixx = lastfree; ixx <= a; ixx++) { if (ixx!=a) { list_next = add(list_next,0,blockend[block]); lastfree++; } regassign[lastfree] = 0; regusage[lastfree] = 1; regblock[lastfree] = blockend[block]; lastfree++; } } else if (o != OP_JMP) { int ixx; for (ixx = lastfree; ixx <= a-1; ixx++) { list_next = add(list_next,0,blockend[block]); lastfree++; regassign[lastfree] = 0; regusage[lastfree] = 1; regblock[lastfree] = blockend[block]; lastfree++; } } } // start code checking for (pc = 0; pc < f->sizecode; pc++) { Instruction instr = f->code[pc]; OpCode o = GET_OPCODE(instr); int a = GETARG_A(instr); int b = GETARG_B(instr); int c = GETARG_C(instr); int bc = GETARG_Bx(instr); int sbc = GETARG_sBx(instr); int dest = 0; int setreg = -1; int setregto = -1; int setreg2 = -1; int loadreg = -1; int loadreg2 = -1; int loadreg3 = -1; int loadregto = -1; int intlocfrom = -1; int intlocto = -1; if ((o==OP_JMP) || (o==OP_FORPREP)) { dest = pc + sbc + 2; } else if ((pc+1!=f->sizecode) && (GET_OPCODE(f->code[pc+1])==OP_JMP)) { dest = pc+1+GETARG_sBx(f->code[pc+1])+2; } // check which registers were read or written to. switch (o) { case OP_MOVE: setreg = a; if (b<=a) { intlocfrom = b; intlocto = b; } loadreg = b; break; case OP_UNM: case OP_NOT: case OP_LEN: setreg = a; loadreg = b; break; case OP_LOADNIL: setreg = a; setregto = b; break; case OP_LOADK: case OP_GETUPVAL: case OP_GETGLOBAL: case OP_LOADBOOL: case OP_NEWTABLE: case OP_CLOSURE: setreg = a; break; case OP_GETTABLE: setreg = a; loadreg = b; if (!IS_CONSTANT(c)) { loadreg2 = c; } break; case OP_SETGLOBAL: case OP_SETUPVAL: loadreg = a; break; case OP_SETTABLE: loadreg = a; if (!IS_CONSTANT(b)) { loadreg2 = b; } if (!IS_CONSTANT(c)) { if (loadreg2==-1) { loadreg2 = c; } else { loadreg3 = c; } if ((a+1!=c) && (c>a)) { intlocto = c-1; } } intlocfrom = 0; if (a-1>=intlocto) { intlocto = a-1; } break; case OP_ADD: case OP_SUB: case OP_MUL: case OP_DIV: case OP_POW: case OP_MOD: setreg = a; if (!IS_CONSTANT(b)) { loadreg = b; } if (!IS_CONSTANT(c)) { if (loadreg==-1) { loadreg = c; } else { loadreg2 = c; } } break; case OP_CONCAT: setreg = a; loadreg = b; loadregto = c; break; case OP_CALL: if (c==0) { setreg = a; setregto = f->maxstacksize; } else if (c>=2) { setreg = a; setregto = a+c-2; } else if (c==1) { intlocfrom = 0; intlocto = a-1; } if (b==0) { loadreg = a; loadregto = f->maxstacksize; } else { loadreg = a; loadregto = a+b-1; } break; case OP_RETURN: if (b==0) { loadreg = a; loadregto = f->maxstacksize; } else if (b>=2) { loadreg = a; loadregto = a+b-2; } break; case OP_TAILCALL: if (b==0) { loadreg = a; loadregto = f->maxstacksize; } else { loadreg = a; loadregto = a+b-1; } break; case OP_VARARG: if (b==0) { setreg = a; setregto = f->maxstacksize; } else { setreg = a; setregto = a+b-1; } break; case OP_SELF: setreg = a; setregto = a+1; loadreg = b; if (a>b) { intlocfrom = 0; intlocto = b; } if (!IS_CONSTANT(c)) { loadreg2 = c; } break; case OP_EQ: case OP_LT: case OP_LE: if (!IS_CONSTANT(b)) { loadreg = b; } if (!IS_CONSTANT(c)) { if (loadreg==-1) { loadreg = c; } else { loadreg2 = c; } } break; case OP_TEST: loadreg = a; break; case OP_TESTSET: setreg = a; loadreg = b; break; case OP_SETLIST: loadreg = a; if (b==0) { loadregto = f->maxstacksize; } else { loadregto = a+b; } break; case OP_FORLOOP: break; case OP_TFORLOOP: break; case OP_FORPREP: loadreg = a; loadregto = a+2; setreg = a; setregto = a+3; intlocfrom = a; intlocto = a+3; regassign[a] = pc; regassign[a+1] = pc; regassign[a+2] = pc; regassign[a+3] = pc+1; regblock[a] = dest; regblock[a+1] = dest; regblock[a+2] = dest; regblock[a+3] = dest-1; block++; blockend[block] = dest-1; if (GET_OPCODE(f->code[dest-2])==OP_JMP) { blockend[block]--; } break; case OP_JMP: if (GET_OPCODE(f->code[dest-1]) == OP_TFORLOOP) { int a = GETARG_A(f->code[dest-1]); int c = GETARG_C(f->code[dest-1]); setreg = a; setregto = a+c+2; loadreg = a; loadregto = a+2; intlocfrom = a; intlocto = a+c+2; regassign[a] = pc; regassign[a+1] = pc; regassign[a+2] = pc; regblock[a] = dest+1; regblock[a+1] = dest+1; regblock[a+2] = dest+1; for (x=a+3;x<=a+c+2;x++) { regassign[x] = pc+1; regblock[x] = dest-1; } } if (dest>pc) { block++; blockend[block] = dest-1; } if (GET_OPCODE(f->code[dest-2])==OP_JMP) { blockend[block]--; } break; case OP_CLOSE: default: break; } for (i=1; i<=block; i++) { x = blockend[i]; i2 = i-1; while ((i2>=0) && (blockend[i2]<x)) { blockend[i2+1] = blockend[i2]; i2 = i2-1; } blockend[i2+1] = x; } if (loadreg!=-1) { if (loadregto==-1) loadregto = loadreg; for (i=loadreg;i<=loadregto;i++) { regusage[i]--; } if (loadreg2!=-1) regusage[loadreg2]--; if (loadreg3!=-1) regusage[loadreg3]--; } if (setreg!=-1) { if (setregto==-1) setregto = setreg; for (i=setreg;i<=setregto;i++) { regusage[i]++; } if (setreg2!=-1) regusage[setreg2]++; } i2 = lastfree-1; for (i=lastfree; i<f->maxstacksize; i++) { if ((regusage[i]<0) || (regusage[i]>1)) { i2 = i; } if ((intlocfrom!=-1) && ((intlocfrom<=i) && (i<=intlocto))) { i2 = i; } } for (i=setreg; i<=setregto; i++) { if (i>i2) { regassign[i] = pc+1; regblock[i] = blockend[block]; } } for (i=lastfree; i<=i2; i++) { //fprintf(stderr,"%d %d %d %d\n",i,regassign[i],regblock[i],block); list_next = add(list_next,regassign[i],regblock[i]); lastfree++; } while (blockend[block] <= pc+1) { block--; } while ((lastfree!=0) && (regblock[lastfree-1] <= pc+1)) { lastfree--; regusage[lastfree]=0; } } // print out information { int length = 0; llist* list = &list_begin; while (list->next!=NULL) { length++; list = list->next; } f->sizelocvars = length; if (f->sizelocvars>0) { f->locvars = luaM_newvector(glstate,f->sizelocvars,LocVar); list = &list_begin; length = 0; while (list->next != NULL) { char names[10]; sprintf(names,"l_%d_%d",main,length); f->locvars[length].varname = luaS_new(glstate, names); f->locvars[length].startpc = list->startpc; f->locvars[length].endpc = list->endpc; length++; list = list->next; } } } deletellist(list_begin.next); // run with all functions for (i=0; i<f->sizep; i++) { luaU_guess_locals(f->p[i],main+i+1); } return 1; }
// match optional expression void match_exp (const char * exp) { int state = 1; pline = exp; while(1) { //printf("state=%d\t",state);getch(); switch(state) { //----------------------------------------------------------------------- // <CONSTANT> => 2 // <ID> => 2 // <UNARY OPR> => 1 // ( => 3 // <FUNC> => 4 case 1: { l_get_token();//printf("[%s]\n",token); if (token_type==OPR_SUB) { token_type = OPR_NEG; move(1); } else if (IS_OPR(token_type) && IS_UNARY_OPR(token_type)) { move(1); } else if (IS_CONSTANT(token_type)) { move(2); } else if (token_type==TT_ID) { move(5); } else if (token_type==TT_LBK) { move(3); } else if (IS_RESWORD(token_type)) { move(4); } else merror_illegal_token(); }break; //----------------------------------------------------------------------- // <OPR> => 1 // <OTHER THINGS!> => END! case 2: { l_get_token();//printf("[%s]\n",token); if (IS_OPR(token_type)) { if(IS_BINARY_OPR(token_type)) { move(1); } else { merror_illegal_token(); } } // END! l_put_back(); return; }break; //----------------------------------------------------------------------- // <EXP> then ) => 2 case 3: { //puts("<match inner expr>"); match_exp(pline); match_str(")"); move(2); }break; //----------------------------------------------------------------------- // ( then <EXP>,<EXP>,<EXP>... then ) => 2 case 4: { int argc = token_ext,i; match_str("("); for(i=0;i<argc;++i) { match_exp(pline); if (i != argc-1) match_str(","); else match_str(")"); } move(2); }break; //----------------------------------------------------------------------- // case 5: { l_get_token(); if (token_type==TT_LBK) { move(3); } else { l_put_back(); move(2); } }break; } } }
static int add_to_variable_list(char *text_line, FORMAT_PTR format) { VARIABLE_PTR var = NULL; char save_char = STR_END; char *token = NULL; char *endptr = NULL; int error = 0; if (!format->variables) { format->variables = dll_init(); if (!format->variables) return(ERR_MEM_LACK); } token = text_line; token = get_token(token, &save_char); if (FF_STRLEN(token)) { var = ff_create_variable(token); if (var == NULL) return ERR_MEM_LACK; #if 0 error = ERR_MEM_LACK; #endif if (var->name[0] == '"' && var->name[strlen(var->name) - 1] == '"') { memmove(var->name, var->name + 1, strlen(var->name) - 2); var->name[strlen(var->name) - 2] = STR_END; } } else { error = err_push(ERR_VARIABLE_DESC, "Expecting a variable name (\"%s\")", format->name); goto add_to_variable_list_exit; } if (!dll_add(format->variables)) { ff_destroy_variable(var); error = ERR_MEM_LACK; goto add_to_variable_list_exit; } dll_assign(var, DLL_VAR, dll_last(format->variables)); token = get_token(token, &save_char); if (FF_STRLEN(token)) { errno = 0; var->start_pos = strtol(token, &endptr, 10); if (errno || FF_STRLEN(endptr)) { error = err_push(errno ? errno : ERR_PARAM_VALUE, "Bad number for variable start position: %s", token); goto add_to_variable_list_exit; } } else { error = err_push(ERR_VARIABLE_DESC, "Expecting a start position for \"%s\"", var->name); goto add_to_variable_list_exit; } token = get_token(token, &save_char); if (FF_STRLEN(token)) { errno = 0; var->end_pos = strtol(token, &endptr, 10); if (errno || FF_STRLEN(endptr)) { error = err_push(errno ? errno : ERR_PARAM_VALUE, "Bad number for variable end position: %s", token); goto add_to_variable_list_exit; } } else { error = err_push(ERR_VARIABLE_DESC, "Expecting an end position for \"%s\"", var->name); goto add_to_variable_list_exit; } token = get_token(token, &save_char); if (FF_STRLEN(token)) { FFV_TYPE(var) = ff_lookup_number(variable_types, token); if (FFV_TYPE(var) == FF_VAR_TYPE_FLAG) { if (os_strncmpi("ARRAY", token, 5) == 0) { RESTORE_CHAR(token, save_char); save_char = STR_END; error = parse_array_variable(&token, var); if (error) goto add_to_variable_list_exit; format->type |= FF_ARRAY; } else { /* Is this a keyworded variable type? If so, remember name of keyword in record_title */ if (IS_KEYWORDED_PARAMETER(token)) { FFV_TYPE(var) = 0; assert(!var->record_title); if (var->record_title) memFree(var->record_title, "var->record_title"); var->record_title = (char *)memStrdup(token, "token"); if (!var->record_title) { error = err_push(ERR_MEM_LACK, ""); goto add_to_variable_list_exit; } } else { error = err_push(ERR_UNKNOWN_VAR_TYPE, token); goto add_to_variable_list_exit; } } } } else { error = err_push(ERR_VARIABLE_DESC, "Expecting a variable type or array description for \"%s\"", var->name); goto add_to_variable_list_exit; } token = get_token(token, &save_char); if (FF_STRLEN(token)) { errno = 0; var->precision = (short)strtol(token, &endptr, 10); if (errno || FF_STRLEN(endptr)) { error = err_push(errno ? errno : ERR_PARAM_VALUE, "Bad number for variable precision: %s", token); goto add_to_variable_list_exit; } } else { if (IS_ARRAY(var)) { error = err_push(ERR_VARIABLE_DESC, "Expecting a precision for \"%s\"", var->name); goto add_to_variable_list_exit; } } if (var->end_pos < var->start_pos) { error = err_push(ERR_VARIABLE_DESC,"End Position < Start Position\n%s", text_line); goto add_to_variable_list_exit; } /* Determine The Variable Type */ if (var->start_pos == 0 && var->end_pos == 0) { if (IS_BINARY(format)) { error = err_push(ERR_UNKNOWN_FORMAT_TYPE, "Illegal to have delimited binary format"); goto add_to_variable_list_exit; } else if (IS_ARRAY(format)) { error = err_push(ERR_UNKNOWN_FORMAT_TYPE, "Illegal to have delimited array format"); goto add_to_variable_list_exit; } format->type |= FFF_VARIED; } if (NEED_TO_CHECK_VARIABLE_SIZE(format, var)) { if (ffv_type_size(var->type) != var->end_pos - var->start_pos + 1) { char save_eol_char = STR_END; char *end_of_line = find_EOL(text_line); if (end_of_line) { save_eol_char = *end_of_line; *end_of_line = STR_END; } error = err_push(ERR_VARIABLE_SIZE,"Expecting ending position for binary field %s to be %d", var->name, var->start_pos + ffv_type_size(var->type) - 1); if (end_of_line) *end_of_line = save_eol_char; goto add_to_variable_list_exit; } } check_old_style_EOL_var(var); /* Does length of CONSTANT variable name equal length of variable? */ if (IS_CONSTANT(var) && !IS_EOL(var)) { if (FF_STRLEN(var->name) > FF_VAR_LENGTH(var)) { error = err_push(ERR_VARIABLE_SIZE, "Constant variable initializer (%s) is too long for field", var->name); goto add_to_variable_list_exit; } else if (FF_STRLEN(var->name) < FF_VAR_LENGTH(var)) error = err_push(ERR_WARNING_ONLY + ERR_VARIABLE_SIZE, "Constant variable initializer (%s) is shorter than field", var->name); } format->num_vars++; format->length = max(format->length, var->end_pos); add_to_variable_list_exit: if (error) { char *cp; char EOL_char = STR_END; /* Don't destroy variable since it will be destroyed in ff_destroy_format */ cp = find_EOL(text_line); if (cp) { EOL_char = *cp; *cp = STR_END; } error = err_push(ERR_VARIABLE_DESC + (error > ERR_WARNING_ONLY ? ERR_WARNING_ONLY : 0),text_line); if (cp) *cp = EOL_char; } RESTORE_CHAR(token, save_char); return(error); }