bool Executor::ExecInsn(Method *method, MethodFrame *frame, Insn *insn) { bool need_suspend = false; switch (insn->op_) { case OP_NUM: { int dst = insn->dst_regs_[0]->id_; const numeric::Width *width = method->method_regs_[dst]->type_.width_; frame->reg_values_[dst].num_ = insn->src_regs_[0]->initial_num_; frame->reg_values_[dst].num_.type = width; } break; case OP_STR: ExecStr(frame, insn); break; case OP_ADD: case OP_SUB: case OP_MUL: case OP_ASSIGN: case OP_GT: case OP_LT: case OP_GTE: case OP_LTE: case OP_EQ: case OP_NE: case OP_LAND: case OP_LOR: case OP_AND: case OP_OR: case OP_XOR: case OP_CONCAT: case OP_LSHIFT: case OP_RSHIFT: ExecBinop(method, frame, insn); break; case OP_CHANNEL_READ: need_suspend = ExecChannelRead(frame, insn); if (need_suspend) { return true; } break; case OP_MEMORY_READ: ExecMemoryRead(frame, insn); break; case OP_FUNCALL: need_suspend = ExecFuncall(frame, insn); break; case OP_FUNCALL_DONE: ExecFuncallDone(method, frame, insn); break; case OP_LOAD_OBJ: ExecLoadObj(frame, insn); break; case OP_IF: ExecIf(frame, insn); // do not increment pc. return false; case OP_GOTO: ExecGoto(frame, insn); // do not increment pc. return false; case OP_NOP: break; case OP_CHANNEL_WRITE: ExecChannelWrite(method, frame, insn); break; case OP_MEMORY_WRITE: ExecMemoryWrite(method, frame, insn); break; case OP_PRE_INC: case OP_PRE_DEC: ExecIncDec(frame, insn); break; case OP_ARRAY_READ: ExecArrayRead(frame, insn); break; case OP_ARRAY_WRITE: ExecArrayWrite(frame, insn); break; case OP_LOGIC_INV: ExecLogicInv(frame, insn); break; case OP_BIT_INV: case OP_PLUS: case OP_MINUS: ExecNumUniop(frame, insn); break; case OP_MEMBER_READ: case OP_MEMBER_WRITE: ExecMemberAccess(frame, insn); break; case OP_BIT_RANGE: ExecBitRange(frame, insn); break; default: CHECK(false) << "unknown insn:" << vm::OpCodeName(insn->op_); } ++frame->pc_; return need_suspend; }
static int chat_UpdateSet(struct fdescriptor *d, fd_set *r, fd_set *w, fd_set *e, int *n) { struct chat *c = descriptor2chat(d); int special, gotabort, gottimeout, needcr; int TimedOut = c->TimedOut; static char arg_term; /* An empty string */ if (c->pause.state == TIMER_RUNNING) return 0; if (TimedOut) { log_Printf(LogCHAT, "Expect timeout\n"); if (c->nargptr == NULL) c->state = CHAT_FAILED; else { /* c->state = CHAT_EXPECT; */ c->argptr = &arg_term; } c->TimedOut = 0; } if (c->state != CHAT_EXPECT && c->state != CHAT_SEND) return 0; gottimeout = gotabort = 0; if (c->arg < c->argc && (c->arg < 0 || *c->argptr == '\0')) { /* Go get the next string */ if (c->arg < 0 || c->state == CHAT_SEND) c->state = CHAT_EXPECT; else c->state = CHAT_SEND; special = 1; while (special && (c->nargptr || c->arg < c->argc - 1)) { if (c->arg < 0 || (!TimedOut && c->state == CHAT_SEND)) c->nargptr = NULL; if (c->nargptr != NULL) { /* We're doing expect-send-expect.... */ c->argptr = c->nargptr; /* Put the '-' back in case we ever want to rerun our script */ c->nargptr[-1] = '-'; c->nargptr = chat_NextChar(c->nargptr, '-'); if (c->nargptr != NULL) *c->nargptr++ = '\0'; } else { int minus; if ((c->argptr = c->argv[++c->arg]) == NULL) { /* End of script - all ok */ c->state = CHAT_DONE; return 0; } if (c->state == CHAT_EXPECT) { /* Look for expect-send-expect sequence */ c->nargptr = c->argptr; minus = 0; while ((c->nargptr = chat_NextChar(c->nargptr, '-'))) { c->nargptr++; minus++; } if (minus % 2) log_Printf(LogWARN, "chat_UpdateSet: \"%s\": Uneven number of" " '-' chars, all ignored\n", c->argptr); else if (minus) { c->nargptr = chat_NextChar(c->argptr, '-'); *c->nargptr++ = '\0'; } } } /* * c->argptr now temporarily points into c->script (via c->argv) * If it's an expect-send-expect sequence, we've just got the correct * portion of that sequence. */ needcr = c->state == CHAT_SEND && (*c->argptr != '!' || c->argptr[1] == '!'); /* We leave room for a potential HDLC header in the target string */ ExpandString(c, c->argptr, c->exp + 2, sizeof c->exp - 2, needcr); /* * Now read our string. If it's not a special string, we unset * ``special'' to break out of the loop. */ if (gotabort) { if (c->abort.num < MAXABORTS) { int len, i; len = strlen(c->exp+2); for (i = 0; i < c->abort.num; i++) if (len > c->abort.string[i].len) { int last; for (last = c->abort.num; last > i; last--) { c->abort.string[last].data = c->abort.string[last-1].data; c->abort.string[last].len = c->abort.string[last-1].len; } break; } c->abort.string[i].len = len; if ((c->abort.string[i].data = (char *)malloc(len+1)) != NULL) { memcpy(c->abort.string[i].data, c->exp+2, len+1); c->abort.num++; } } else log_Printf(LogERROR, "chat_UpdateSet: too many abort strings\n"); gotabort = 0; } else if (gottimeout) { c->TimeoutSec = atoi(c->exp + 2); if (c->TimeoutSec <= 0) c->TimeoutSec = 30; gottimeout = 0; } else if (c->nargptr == NULL && !strcmp(c->exp+2, "ABORT")) gotabort = 1; else if (c->nargptr == NULL && !strcmp(c->exp+2, "TIMEOUT")) gottimeout = 1; else { if (c->exp[2] == '!' && c->exp[3] != '!') ExecStr(c->physical, c->exp + 3, c->exp + 3, sizeof c->exp - 3); if (c->exp[2] == '\0') { /* Empty string, reparse (this may be better as a `goto start') */ c->argptr = &arg_term; return chat_UpdateSet(d, r, w, e, n); } special = 0; } } if (special) { if (gottimeout) log_Printf(LogWARN, "chat_UpdateSet: TIMEOUT: Argument expected\n"); else if (gotabort) log_Printf(LogWARN, "chat_UpdateSet: ABORT: Argument expected\n"); /* End of script - all ok */ c->state = CHAT_DONE; return 0; } /* set c->argptr to point in the right place */ c->argptr = c->exp + (c->exp[2] == '!' ? 3 : 2); c->arglen = strlen(c->argptr); if (c->state == CHAT_EXPECT) { /* We must check to see if the string's already been found ! */ char *begin, *end; end = c->bufend - c->arglen + 1; if (end < c->bufstart) end = c->bufstart; for (begin = c->bufstart; begin < end; begin++) if (!strncmp(begin, c->argptr, c->arglen)) { c->bufstart = begin + c->arglen; c->argptr += c->arglen; c->arglen = 0; /* Continue - we've already read our expect string */ return chat_UpdateSet(d, r, w, e, n); } log_Printf(LogCHAT, "Expect(%d): %s\n", c->TimeoutSec, c->argptr); chat_SetTimeout(c); } } /* * We now have c->argptr pointing at what we want to expect/send and * c->state saying what we want to do... we now know what to put in * the fd_set :-) */ if (c->state == CHAT_EXPECT) return physical_doUpdateSet(&c->physical->desc, r, NULL, e, n, 1); else return physical_doUpdateSet(&c->physical->desc, NULL, w, e, n, 1); }