static int generate_internal(MarkovData* data, int max_words, int (*output_func)(const char*, void*), void* output_data) { if (! data->initialized) return 1; if (max_words == 0) max_words = data->output_words; const char* prefix[data->prefix_len]; prepopulate_prefix(data, prefix); srand( (unsigned int) time(NULL)); while(max_words-- > 0) { StateNode* state = lookup_state(data, prefix); //possibly should check for null, but should always exist const char* word = NULL; int count = 0; for(SuffixNode* s = state->list; s != NULL; s = s->next) { if (rand() % ++count == 0) { word = s->suffix; } } if (strcmp(word, data->sentinel_word) == 0) { break; } if (output_func(word, output_data)) return 1; rotate_prefix(data, prefix, word); } return 0; }
static int EmitRescaledAlphaRGB(const VP8Io* const io, WebPDecParams* const p) { if (io->a != NULL) { int (* const output_func)(WebPDecParams* const, int) = (p->output->colorspace == MODE_RGBA_4444) ? ExportAlphaRGBA4444 : ExportAlpha; WebPRescaler* const scaler = &p->scaler_a; int j = 0, pos = 0; while (j < io->mb_h) { j += Import(io->a + j * io->width, io->width, io->mb_h - j, scaler); pos += output_func(p, pos); } } return 0; }
static gboolean output_query_results (MuMsgIter *iter, MuConfig *opts, GError **err) { int count; gboolean rv; OutputFunc *output_func; output_func = output_prepare (opts, err); if (!output_func) return FALSE; for (count = 0, rv = TRUE; !mu_msg_iter_is_done(iter); mu_msg_iter_next (iter)) { MuMsg *msg; if (count == opts->maxnum) break; msg = get_message (iter, opts->after); if (!msg) break; /* { */ /* const char* thread_id; */ /* thread_id = mu_msg_iter_get_thread_id (iter); */ /* g_print ("%s ", thread_id ? thread_id : "<none>"); */ /* } */ rv = output_func (msg, iter, opts, err); if (!rv) break; else ++count; } output_finish (opts); if (rv && count == 0) { mu_util_g_set_error (err, MU_ERROR_NO_MATCHES, "no matches for search expression"); return FALSE; } return rv; }
static gboolean output_query_results (MuMsgIter *iter, MuConfig *opts, GError **err) { unsigned count; gboolean rv; OutputFunc *output_func; output_func = output_prepare (opts, err); if (!output_func) return FALSE; for (count = 0, rv = TRUE; !mu_msg_iter_is_done(iter); mu_msg_iter_next (iter)) { MuMsg *msg; msg = get_message (iter, opts->after); if (!msg) break; rv = output_func (msg, iter, opts, err); if (!rv) break; else ++count; } output_finish (opts); if (rv && count == 0) { mu_util_g_set_error (err, MU_ERROR_NO_MATCHES, "no matches for search expression"); return FALSE; } return rv; }
int stty_main(int argc UNUSED_PARAM, char **argv) { struct termios mode; void (*output_func)(const struct termios *, int); const char *file_name = NULL; int display_all = 0; int stty_state; int k; INIT_G(); stty_state = STTY_noargs; output_func = do_display; /* First pass: only parse/verify command line params */ k = 0; while (argv[++k]) { const struct mode_info *mp; const struct control_info *cp; const char *arg = argv[k]; const char *argnext = argv[k+1]; int param; if (arg[0] == '-') { int i; mp = find_mode(arg+1); if (mp) { if (!(mp->flags & REV)) goto invalid_argument; stty_state &= ~STTY_noargs; continue; } /* It is an option - parse it */ i = 0; while (arg[++i]) { switch (arg[i]) { case 'a': stty_state |= STTY_verbose_output; output_func = do_display; display_all = 1; break; case 'g': stty_state |= STTY_recoverable_output; output_func = display_recoverable; break; case 'F': if (file_name) bb_error_msg_and_die("only one device may be specified"); file_name = &arg[i+1]; /* "-Fdevice" ? */ if (!file_name[0]) { /* nope, "-F device" */ int p = k+1; /* argv[p] is argnext */ file_name = argnext; if (!file_name) bb_error_msg_and_die(bb_msg_requires_arg, "-F"); /* remove -F param from arg[vc] */ while (argv[p]) { argv[p] = argv[p+1]; ++p; } } goto end_option; default: goto invalid_argument; } } end_option: continue; } mp = find_mode(arg); if (mp) { stty_state &= ~STTY_noargs; continue; } cp = find_control(arg); if (cp) { if (!argnext) bb_error_msg_and_die(bb_msg_requires_arg, arg); /* called for the side effect of xfunc death only */ set_control_char_or_die(cp, argnext, &mode); stty_state &= ~STTY_noargs; ++k; continue; } param = find_param(arg); if (param & param_need_arg) { if (!argnext) bb_error_msg_and_die(bb_msg_requires_arg, arg); ++k; } switch (param) { #ifdef __linux__ case param_line: # ifndef TIOCGWINSZ xatoul_range_sfx(argnext, 1, INT_MAX, stty_suffixes); break; # endif /* else fall-through */ #endif #ifdef TIOCGWINSZ case param_rows: case param_cols: case param_columns: xatoul_range_sfx(argnext, 1, INT_MAX, stty_suffixes); break; case param_size: #endif case param_speed: break; case param_ispeed: /* called for the side effect of xfunc death only */ set_speed_or_die(input_speed, argnext, &mode); break; case param_ospeed: /* called for the side effect of xfunc death only */ set_speed_or_die(output_speed, argnext, &mode); break; default: if (recover_mode(arg, &mode) == 1) break; if (tty_value_to_baud(xatou(arg)) != (speed_t) -1) break; invalid_argument: bb_error_msg_and_die("invalid argument '%s'", arg); } stty_state &= ~STTY_noargs; } /* Specifying both -a and -g is an error */ if ((stty_state & (STTY_verbose_output | STTY_recoverable_output)) == (STTY_verbose_output | STTY_recoverable_output) ) { bb_error_msg_and_die("-a and -g are mutually exclusive"); } /* Specifying -a or -g with non-options is an error */ if ((stty_state & (STTY_verbose_output | STTY_recoverable_output)) && !(stty_state & STTY_noargs) ) { bb_error_msg_and_die("modes may not be set when -a or -g is used"); } /* Now it is safe to start doing things */ if (file_name) { G.device_name = file_name; xmove_fd(xopen_nonblocking(G.device_name), STDIN_FILENO); ndelay_off(STDIN_FILENO); } /* Initialize to all zeroes so there is no risk memcmp will report a spurious difference in an uninitialized portion of the structure */ memset(&mode, 0, sizeof(mode)); if (tcgetattr(STDIN_FILENO, &mode)) perror_on_device_and_die("%s"); if (stty_state & (STTY_verbose_output | STTY_recoverable_output | STTY_noargs)) { G.max_col = get_terminal_width(STDOUT_FILENO); output_func(&mode, display_all); return EXIT_SUCCESS; } /* Second pass: perform actions */ k = 0; while (argv[++k]) { const struct mode_info *mp; const struct control_info *cp; const char *arg = argv[k]; const char *argnext = argv[k+1]; int param; if (arg[0] == '-') { mp = find_mode(arg+1); if (mp) { set_mode(mp, 1 /* reversed */, &mode); stty_state |= STTY_require_set_attr; } /* It is an option - already parsed. Skip it */ continue; } mp = find_mode(arg); if (mp) { set_mode(mp, 0 /* non-reversed */, &mode); stty_state |= STTY_require_set_attr; continue; } cp = find_control(arg); if (cp) { ++k; set_control_char_or_die(cp, argnext, &mode); stty_state |= STTY_require_set_attr; continue; } param = find_param(arg); if (param & param_need_arg) { ++k; } switch (param) { #ifdef __linux__ case param_line: mode.c_line = xatoul_sfx(argnext, stty_suffixes); stty_state |= STTY_require_set_attr; break; #endif #ifdef TIOCGWINSZ case param_cols: case param_columns: set_window_size(-1, xatoul_sfx(argnext, stty_suffixes)); break; case param_size: display_window_size(0); break; case param_rows: set_window_size(xatoul_sfx(argnext, stty_suffixes), -1); break; #endif case param_speed: display_speed(&mode, 0); break; case param_ispeed: set_speed_or_die(input_speed, argnext, &mode); stty_state |= (STTY_require_set_attr | STTY_speed_was_set); break; case param_ospeed: set_speed_or_die(output_speed, argnext, &mode); stty_state |= (STTY_require_set_attr | STTY_speed_was_set); break; default: if (recover_mode(arg, &mode) == 1) stty_state |= STTY_require_set_attr; else /* true: if (tty_value_to_baud(xatou(arg)) != (speed_t) -1) */{ set_speed_or_die(both_speeds, arg, &mode); stty_state |= (STTY_require_set_attr | STTY_speed_was_set); } /* else - impossible (caught in the first pass): bb_error_msg_and_die("invalid argument '%s'", arg); */ } } if (stty_state & STTY_require_set_attr) { struct termios new_mode; if (tcsetattr(STDIN_FILENO, TCSADRAIN, &mode)) perror_on_device_and_die("%s"); /* POSIX (according to Zlotnick's book) tcsetattr returns zero if it performs *any* of the requested operations. This means it can report 'success' when it has actually failed to perform some proper subset of the requested operations. To detect this partial failure, get the current terminal attributes and compare them to the requested ones */ /* Initialize to all zeroes so there is no risk memcmp will report a spurious difference in an uninitialized portion of the structure */ memset(&new_mode, 0, sizeof(new_mode)); if (tcgetattr(STDIN_FILENO, &new_mode)) perror_on_device_and_die("%s"); if (memcmp(&mode, &new_mode, sizeof(mode)) != 0) { /* * I think the below chunk is not necessary on Linux. * If you are deleting it, also delete STTY_speed_was_set bit - * it is only ever checked here. */ #if 0 /* was "if CIBAUD" */ /* SunOS 4.1.3 (at least) has the problem that after this sequence, tcgetattr (&m1); tcsetattr (&m1); tcgetattr (&m2); sometimes (m1 != m2). The only difference is in the four bits of the c_cflag field corresponding to the baud rate. To save Sun users a little confusion, don't report an error if this happens. But suppress the error only if we haven't tried to set the baud rate explicitly -- otherwise we'd never give an error for a true failure to set the baud rate */ new_mode.c_cflag &= (~CIBAUD); if ((stty_state & STTY_speed_was_set) || memcmp(&mode, &new_mode, sizeof(mode)) != 0) #endif perror_on_device_and_die("%s: cannot perform all requested operations"); } } return EXIT_SUCCESS; }
static int _xd3_main_input (xd3_cmd cmd, _xd3_file *ifile, _xd3_file *ofile, _xd3_file *sfile) { int ret; xd3_stream stream; size_t nread = 0; usize_t winsize; int stream_flags = 0; xd3_config config; xd3_source source; xoff_t last_total_in = 0; xoff_t last_total_out = 0; long start_time; int stdout_only = 0; int (*input_func) (xd3_stream*); int (*output_func) (xd3_stream*, _xd3_file *); memset (& stream, 0, sizeof (stream)); memset (& source, 0, sizeof (source)); memset (& config, 0, sizeof (config)); config.alloc = _xd3_alloc; config.freef = _xd3_free1; config.iopt_size = option_iopt_size; config.sprevsz = option_sprevsz; start_time = get_millisecs_now (); if (option_use_checksum) { stream_flags |= XD3_ADLER32; } /* main_input setup. */ switch ((int) cmd) { #if VCDIFF_TOOLS if (1) { case CMD_PRINTHDR: stream_flags |= XD3_JUST_HDR; } else if (1) { case CMD_PRINTHDRS: stream_flags |= XD3_SKIP_WINDOW; } else { case CMD_PRINTDELTA: stream_flags |= XD3_SKIP_EMIT; } ifile->flags |= RD_NONEXTERNAL; input_func = xd3_decode_input; output_func = main_print_func; stream_flags |= XD3_ADLER32_NOVER; stdout_only = 1; break; case CMD_RECODE: case CMD_MERGE: case CMD_MERGE_ARG: /* No source will be read */ stream_flags |= XD3_ADLER32_NOVER | XD3_SKIP_EMIT; ifile->flags |= RD_NONEXTERNAL; input_func = xd3_decode_input; if ((ret = main_init_recode_stream ())) { return (SHERR_INVAL); } if (cmd == CMD_RECODE) { output_func = main_recode_func; } else { output_func = _xd3_merge_func; } break; #endif /* VCDIFF_TOOLS */ #if XD3_ENCODER case CMD_ENCODE: input_func = xd3_encode_input; output_func = _xd3_write_output; if (option_no_compress) { stream_flags |= XD3_NOCOMPRESS; } { if (option_level == 0) { stream_flags |= XD3_NOCOMPRESS; config.smatch_cfg = XD3_SMATCH_FASTEST; } else if (option_level == 1) { config.smatch_cfg = XD3_SMATCH_FASTEST; } else if (option_level == 2) { config.smatch_cfg = XD3_SMATCH_FASTER; } else if (option_level <= 5) { config.smatch_cfg = XD3_SMATCH_FAST; } else if (option_level == 6) { config.smatch_cfg = XD3_SMATCH_DEFAULT; } else { config.smatch_cfg = XD3_SMATCH_SLOW; } } break; #endif case CMD_DECODE: if (option_use_checksum == 0) { stream_flags |= XD3_ADLER32_NOVER; } ifile->flags |= RD_NONEXTERNAL; input_func = xd3_decode_input; output_func = _xd3_write_output; break; default: XPR(NT "internal error\n"); return (SHERR_INVAL); } main_bsize = winsize = _xd3_get_winsize (ifile); if (!(main_bdata = (uint8_t*)_xd3_alloc(NULL, 1, winsize))) { return (SHERR_NOMEM); } config.winsize = winsize; config.getblk = _xd3_getblk_func; config.flags = stream_flags; if ((ret = xd3_config_stream (& stream, & config))) { return (SHERR_INVAL); } #if VCDIFF_TOOLS if ((cmd == CMD_MERGE || cmd == CMD_MERGE_ARG) && (ret = xd3_whole_state_init (& stream))) { XPR(NT XD3_LIB_ERRMSG (& stream, ret)); return (SHERR_INVAL); } #endif if (cmd != CMD_DECODE) { /* When not decoding, set source now. The decoder delays this * step until XD3_GOTHEADER. */ if (sfile && sfile->filename != NULL) { if ((ret = _xd3_set_source (& stream, cmd, sfile, & source))) { return (SHERR_INVAL); } XD3_ASSERT(stream.src != NULL); } } /* This times each window. */ get_millisecs_since (); /* Main input loop. */ do { xoff_t input_offset; xoff_t input_remain; usize_t try_read; input_offset = ifile->nread; input_remain = XOFF_T_MAX - input_offset; try_read = (usize_t) min ((xoff_t) config.winsize, input_remain); ret = _xd3_read_primary_input(ifile, main_bdata, try_read, &nread); if (ret != 0) return (SHERR_IO); /* If we've reached EOF tell the stream to flush. */ if (nread < try_read) { stream.flags |= XD3_FLUSH; } #if XD3_ENCODER /* After the first _xd3_read_primary_input completes, we know * all the information needed to encode the application * header. */ if (cmd == CMD_ENCODE && (ret = _xd3_set_appheader (& stream, ifile, sfile))) { return (SHERR_INVAL); } #endif xd3_avail_input (& stream, main_bdata, nread); /* If we read zero bytes after encoding at least one window... */ if (nread == 0 && stream.current_window > 0) { break; } again: ret = input_func (& stream); switch (ret) { case XD3_INPUT: continue; case XD3_GOTHEADER: { XD3_ASSERT (stream.current_window == 0); /* Need to process the appheader as soon as possible. It may * contain a suggested default filename/decompression routine for * the ofile, and it may contain default/decompression routine for * the sources. */ if (cmd == CMD_DECODE) { /* May need to set the sfile->filename if none was given. */ _xd3_get_appheader (& stream, ifile, ofile, sfile); /* Now open the source file. */ if ((sfile->filename != NULL) && (ret = _xd3_set_source (& stream, cmd, sfile, & source))) { return (SHERR_INVAL); } } } /* FALLTHROUGH */ case XD3_WINSTART: { /* e.g., set or unset XD3_SKIP_WINDOW. */ goto again; } case XD3_OUTPUT: { /* Defer opening the output file until the stream produces its * first output for both encoder and decoder, this way we * delay long enough for the decoder to receive the * application header. (Or longer if there are skipped * windows, but I can't think of any reason not to delay * open.) */ if (ofile != NULL && ! _xd3_file_isopen (ofile) && (ret = _xd3_open_output (& stream, ofile)) != 0) { return (SHERR_INVAL); } if ((ret = output_func (& stream, ofile)) && (ret != PRINTHDR_SPECIAL)) { return (SHERR_INVAL); } if (ret == PRINTHDR_SPECIAL) { xd3_abort_stream (& stream); ret = 0; goto done; } ret = 0; xd3_consume_output (& stream); goto again; } case XD3_WINFINISH: { goto again; } default: /* input_func() error */ if (! option_quiet && ret == XD3_INVALID_INPUT) { XPR(NT "normally this indicates that the source file is incorrect\n"); XPR(NT "please verify the source file with sha1sum or equivalent\n"); } return (SHERR_INVAL); } } while (nread == config.winsize); done: /* Close the inputs. (ifile must be open, sfile may be open) */ _xd3_file_close (ifile); if (sfile != NULL) { _xd3_file_close (sfile); } /* If output file is not open yet because of delayed-open, it means * we never encountered a window in the delta, but it could have had * a VCDIFF header? TODO: solve this elsewhere. For now, it prints * "nothing to output" below, but the check doesn't happen in case * of option_no_output. */ if (! option_no_output && ofile != NULL) { if (!stdout_only && ! _xd3_file_isopen (ofile)) { XPR(NT "nothing to output: %s\n", ifile->filename); return (SHERR_INVAL); } /* Have to close the output before calling * main_external_compression_finish, or else it hangs. */ if (_xd3_file_close (ofile) != 0) { return (SHERR_INVAL); } } #if EXTERNAL_COMPRESSION if ((ret = main_external_compression_finish ())) { XPR(NT "external compression commands failed\n"); return (SHERR_INVAL); } #endif if ((ret = xd3_close_stream (& stream))) { return (SHERR_INVAL); } xd3_free_stream (& stream); return (0); }
static int retrieve_file_data(struct globals *state, FILE *dfp, int (*progress)(void *data, int current, int total), int (*output_func)(void *data, char *bytes, int len), void *data) { char buf[4*1024]; /* made bigger to speed up local xfers */ unsigned second_cnt; struct pollfd polldata; polldata.fd = fileno(dfp); polldata.events = POLLIN | POLLPRI; progress(data, 0, state->total_len); if (state->chunked) goto get_clen; /* Loops only if chunked */ while (1) { ndelay_on(polldata.fd); while (1) { int n; unsigned rdsz; rdsz = sizeof(buf); if (state->got_clen) { if (state->content_len < (off_t)sizeof(buf)) { if ((int)state->content_len <= 0) break; rdsz = (unsigned)state->content_len; } } second_cnt = state->timeout_seconds; while (1) { if (safe_poll(&polldata, 1, 1000) != 0) break; /* error, EOF, or data is available */ if (second_cnt != 0 && --second_cnt == 0) { progress(data, -1, state->total_len); ERROR("download timed out"); return -1; } /* Needed for "stalled" indicator */ progress(data, state->transferred, state->total_len); } /* fread internally uses read loop, which in our case * is usually exited when we get EAGAIN. * In this case, libc sets error marker on the stream. * Need to clear it before next fread to avoid possible * rare false positive ferror below. Rare because usually * fread gets more than zero bytes, and we don't fall * into if (n <= 0) ... */ clearerr(dfp); errno = 0; n = safe_fread(buf, rdsz, dfp); /* man fread: * If error occurs, or EOF is reached, the return value * is a short item count (or zero). * fread does not distinguish between EOF and error. */ if (n <= 0) { if (errno == EAGAIN) /* poll lied, there is no data? */ continue; /* yes */ if (ferror(dfp)) ERROR("Could not read file"); break; /* EOF, not error */ } output_func(data, buf, n); state->transferred += n; progress(data, state->transferred, state->total_len); if (state->got_clen) { state->content_len -= n; if (state->content_len == 0) break; } } ndelay_off(polldata.fd); if (!state->chunked) break; safe_fgets(buf, sizeof(buf), dfp); /* This is a newline */ get_clen: safe_fgets(buf, sizeof(buf), dfp); state->content_len = strtol(buf, NULL, 16); /* FIXME: error check? */ if (state->content_len == 0) break; /* all done! */ state->got_clen = 1; } progress(data, state->transferred, state->total_len); return 0; }
void tTJSInterCodeContext::Disassemble( void (*output_func)(const tjs_char *msg, const tjs_char *comment, tjs_int addr, const tjs_int32 *codestart, tjs_int size, void *data), void (*output_func_src)(const tjs_char *msg, const tjs_char *name, tjs_int line, void *data), void *data, tjs_int start, tjs_int end) { // dis-assemble the intermediate code. // "output_func" points a line output function. // tTJSVariantString * s; tTJSString msg; tTJSString com; tjs_int prevline = -1; tjs_int curline = -1; if(end <= 0) end = CodeAreaSize; if(end > CodeAreaSize) end = CodeAreaSize; for(tjs_int i = start; i < end; ) { msg.Clear(); com.Clear(); tjs_int size; tjs_int srcpos = CodePosToSrcPos(i); tjs_int line = Block->SrcPosToLine(srcpos); // output source lines as comment if(curline == -1 || curline <= line) { if(curline == -1) curline = line; tjs_int nl = line - curline; while(curline <= line) { if(nl<3 || nl >= 3 && line-curline <= 2) { tjs_int len; tjs_char *src = Block->GetLine(curline, &len); tjs_char * buf = new tjs_char[len + 1]; TJS_strcpy_maxlen(buf, src, len); try { output_func_src(buf, TJS_W(""), curline, data); } catch(...) { delete [] buf; throw; } delete [] buf; curline++; } else { curline = line - 2; } } } else if(prevline != line) { tjs_int len; tjs_char *src = Block->GetLine(line, &len); tjs_char * buf = new tjs_char[len + 1]; TJS_strcpy_maxlen(buf, src, len); try { output_func_src((const tjs_char*)buf, TJS_W(""), line, data); } catch(...) { delete [] buf; throw; } delete [] buf; } prevline = line; // decode each instructions switch(CodeArea[i]) { case VM_NOP: msg.printf(TJS_W("nop")); size = 1; break; case VM_NF: msg.printf(TJS_W("nf")); size = 1; break; case VM_CONST: msg.printf(TJS_W("const %%%d, *%d"), TJS_FROM_VM_REG_ADDR(CodeArea[i+1]), TJS_FROM_VM_REG_ADDR(CodeArea[i+2])); if(DataArea) { com.printf(TJS_W("*%d = %ls"), TJS_FROM_VM_REG_ADDR(CodeArea[i+2]), GetValueComment(TJS_GET_VM_REG(DataArea, CodeArea[i+2])).c_str()); } size = 3; break; #define OP2_DISASM(c, x) \ case c: \ msg.printf(TJS_W(x) TJS_W(" %%%d, %%%d"), TJS_FROM_VM_REG_ADDR(CodeArea[i+1]), \ TJS_FROM_VM_REG_ADDR(CodeArea[i+2])); \ size = 3; \ break // instructions that // 1. have two operands that represent registers. // 2. do not have property access variants. OP2_DISASM(VM_CP, "cp"); OP2_DISASM(VM_CEQ, "ceq"); OP2_DISASM(VM_CDEQ, "cdeq"); OP2_DISASM(VM_CLT, "clt"); OP2_DISASM(VM_CGT, "cgt"); OP2_DISASM(VM_CHKINS, "chkins"); #undef OP2_DISASM #define OP2_DISASM(c, x) \ case c: \ msg.printf(TJS_W(x) TJS_W(" %%%d, %%%d"), TJS_FROM_VM_REG_ADDR(CodeArea[i+1]), \ TJS_FROM_VM_REG_ADDR(CodeArea[i+2])); \ size = 3; \ break; \ case c+1: \ msg.printf(TJS_W(x) TJS_W("pd") TJS_W(" %%%d, %%%d.*%d, %%%d"), \ TJS_FROM_VM_REG_ADDR(CodeArea[i+1]), \ TJS_FROM_VM_REG_ADDR(CodeArea[i+2]), \ TJS_FROM_VM_REG_ADDR(CodeArea[i+3]), \ TJS_FROM_VM_REG_ADDR(CodeArea[i+4])); \ if(DataArea) \ { \ com.printf(TJS_W("*%d = %ls"), TJS_FROM_VM_REG_ADDR(CodeArea[i+3]), \ GetValueComment(TJS_GET_VM_REG(DataArea, CodeArea[i+3])).c_str()); \ } \ size = 5; \ break; \ case c+2: \ msg.printf(TJS_W(x) TJS_W("pi") TJS_W(" %%%d, %%%d.%%%d, %%%d"), \ TJS_FROM_VM_REG_ADDR(CodeArea[i+1]), \ TJS_FROM_VM_REG_ADDR(CodeArea[i+2]), \ TJS_FROM_VM_REG_ADDR(CodeArea[i+3]), \ TJS_FROM_VM_REG_ADDR(CodeArea[i+4])); \ size = 5; \ break; \ case c+3: \ msg.printf(TJS_W(x) TJS_W("p") TJS_W(" %%%d, %%%d, %%%d"), \ TJS_FROM_VM_REG_ADDR(CodeArea[i+1]), \ TJS_FROM_VM_REG_ADDR(CodeArea[i+2]), \ TJS_FROM_VM_REG_ADDR(CodeArea[i+3])); \ size = 4; \ break // instructions that // 1. have two operands that represent registers. // 2. have property access variants OP2_DISASM(VM_LOR, "lor"); OP2_DISASM(VM_LAND, "land"); OP2_DISASM(VM_BOR, "bor"); OP2_DISASM(VM_BXOR, "bxor"); OP2_DISASM(VM_BAND, "band"); OP2_DISASM(VM_SAR, "sar"); OP2_DISASM(VM_SAL, "sal"); OP2_DISASM(VM_SR, "sr"); OP2_DISASM(VM_ADD, "add"); OP2_DISASM(VM_SUB, "sub"); OP2_DISASM(VM_MOD, "mod"); OP2_DISASM(VM_DIV, "div"); OP2_DISASM(VM_IDIV, "idiv"); OP2_DISASM(VM_MUL, "mul"); #undef OP2_DISASM #define OP1_DISASM(x) \ msg.printf(TJS_W(x) TJS_W(" %%%d"), TJS_FROM_VM_REG_ADDR(CodeArea[i+1])); \ size = 2 // instructions that have one operand which represent a register, // except for inc, dec case VM_TT: OP1_DISASM("tt"); break; case VM_TF: OP1_DISASM("tf"); break; case VM_SETF: OP1_DISASM("setf"); break; case VM_SETNF: OP1_DISASM("setnf"); break; case VM_LNOT: OP1_DISASM("lnot"); break; case VM_BNOT: OP1_DISASM("bnot"); break; case VM_ASC: OP1_DISASM("asc"); break; case VM_CHR: OP1_DISASM("chr"); break; case VM_NUM: OP1_DISASM("num"); break; case VM_CHS: OP1_DISASM("chs"); break; case VM_CL: OP1_DISASM("cl"); break; case VM_INV: OP1_DISASM("inv"); break; case VM_CHKINV: OP1_DISASM("chkinv"); break; case VM_TYPEOF: OP1_DISASM("typeof"); break; case VM_EVAL: OP1_DISASM("eval"); break; case VM_EEXP: OP1_DISASM("eexp"); break; case VM_INT: OP1_DISASM("int"); break; case VM_REAL: OP1_DISASM("real"); break; case VM_STR: OP1_DISASM("str"); break; case VM_OCTET: OP1_DISASM("octet"); break; #undef OP1_DISASM case VM_CCL: msg.printf(TJS_W("ccl %%%d-%%%d"), TJS_FROM_VM_REG_ADDR(CodeArea[i+1]), TJS_FROM_VM_REG_ADDR(CodeArea[i+1]) + CodeArea[i+2] -1); size = 3; break; #define OP1_DISASM(c, x) \ case c: \ msg.printf(TJS_W(x) TJS_W(" %%%d"), TJS_FROM_VM_REG_ADDR(CodeArea[i+1])); \ size = 2; \ break; \ case c+1: \ msg.printf(TJS_W(x) TJS_W("pd") TJS_W(" %%%d, %%%d.*%d"), \ TJS_FROM_VM_REG_ADDR(CodeArea[i+1]), \ TJS_FROM_VM_REG_ADDR(CodeArea[i+2]), \ TJS_FROM_VM_REG_ADDR(CodeArea[i+3])); \ if(DataArea) \ { \ com.printf(TJS_W("*%d = %ls"), \ TJS_FROM_VM_REG_ADDR(CodeArea[i+3]), \ GetValueComment(TJS_GET_VM_REG(DataArea, CodeArea[i+3])).c_str()); \ } \ size = 4; \ break; \ case c+2: \ msg.printf(TJS_W(x) TJS_W("pi") TJS_W(" %%%d, %%%d.%%%d"), \ TJS_FROM_VM_REG_ADDR(CodeArea[i+1]), \ TJS_FROM_VM_REG_ADDR(CodeArea[i+2]), \ TJS_FROM_VM_REG_ADDR(CodeArea[i+3])); \ size = 4; \ break; \ case c+3: \ msg.printf(TJS_W(x) TJS_W("p") TJS_W(" %%%d, %%%d"), \ TJS_FROM_VM_REG_ADDR(CodeArea[i+1]), \ TJS_FROM_VM_REG_ADDR(CodeArea[i+2])); \ size = 3; \ break // inc and dec OP1_DISASM(VM_INC, "inc"); OP1_DISASM(VM_DEC, "dec"); #undef OP1_DISASM #define OP1A_DISASM(x) \ msg.printf(TJS_W(x) TJS_W(" %09d"), TJS_FROM_VM_CODE_ADDR(CodeArea[i+1]) + i); \ size = 2 // instructions that have one operand which represents code area case VM_JF: OP1A_DISASM("jf"); break; case VM_JNF: OP1A_DISASM("jnf"); break; case VM_JMP: OP1A_DISASM("jmp"); break; #undef OP1A_DISASM case VM_CALL: case VM_CALLD: case VM_CALLI: case VM_NEW: { // function call variants msg.printf( CodeArea[i] == VM_CALL ?TJS_W("call %%%d, %%%d("): CodeArea[i] == VM_CALLD ?TJS_W("calld %%%d, %%%d.*%d("): CodeArea[i] == VM_CALLI ?TJS_W("calli %%%d, %%%d.%%%d("): TJS_W("new %%%d, %%%d("), TJS_FROM_VM_REG_ADDR(CodeArea[i+1]), TJS_FROM_VM_REG_ADDR(CodeArea[i+2]), TJS_FROM_VM_REG_ADDR(CodeArea[i+3])); tjs_int st; // start of arguments if(CodeArea[i] == VM_CALLD || CodeArea[i] == VM_CALLI) st = 5; else st = 4; tjs_int num = CodeArea[i+st-1]; // st-1 = argument count bool first = true; tjs_char buf[256]; tjs_int c = 0; if(num == -1) { // omit arg size = st; msg += TJS_W("..."); } else if(num == -2) { // expand arg st ++; num = CodeArea[i+st-1]; size = st + num * 2; for(tjs_int j = 0; j < num; j++) { if(!first) msg += TJS_W(", "); first = false; switch(CodeArea[i+st+j*2]) { case fatNormal: TJS_snprintf(buf, sizeof(buf)/sizeof(tjs_char), TJS_W("%%%d"), TJS_FROM_VM_REG_ADDR(CodeArea[i+st+j*2+1])); break; case fatExpand: TJS_snprintf(buf, sizeof(buf)/sizeof(tjs_char), TJS_W("%%%d*"), TJS_FROM_VM_REG_ADDR(CodeArea[i+st+j*2+1])); break; case fatUnnamedExpand: TJS_strcpy(buf, TJS_W("*")); break; } msg += buf; } } else { // normal operation size = st + num; while(num--) { if(!first) msg += TJS_W(", "); first = false; TJS_snprintf(buf, sizeof(buf)/sizeof(tjs_char), TJS_W("%%%d"), TJS_FROM_VM_REG_ADDR(CodeArea[i+c+st])); c++; msg += buf; } } msg += TJS_W(")"); if(DataArea && CodeArea[i] == VM_CALLD) { com.printf(TJS_W("*%d = %ls"), TJS_FROM_VM_REG_ADDR(CodeArea[i+3]), GetValueComment(TJS_GET_VM_REG(DataArea, CodeArea[i+3])).c_str()); } break; } case VM_GPD: case VM_GPDS: // property get direct msg.printf( CodeArea[i] == VM_GPD?TJS_W("gpd %%%d, %%%d.*%d"): TJS_W("gpds %%%d, %%%d.*%d"), TJS_FROM_VM_REG_ADDR(CodeArea[i+1]), TJS_FROM_VM_REG_ADDR(CodeArea[i+2]), TJS_FROM_VM_REG_ADDR(CodeArea[i+3])); if(DataArea) { com.printf(TJS_W("*%d = %ls"), TJS_FROM_VM_REG_ADDR(CodeArea[i+3]), GetValueComment(TJS_GET_VM_REG(DataArea, CodeArea[i+3])).c_str()); } size = 4; break; case VM_SPD: case VM_SPDE: case VM_SPDEH: case VM_SPDS: // property set direct msg.printf( CodeArea[i] == VM_SPD ? TJS_W("spd %%%d.*%d, %%%d"): CodeArea[i] == VM_SPDE? TJS_W("spde %%%d.*%d, %%%d"): CodeArea[i] == VM_SPDEH?TJS_W("spdeh %%%d.*%d, %%%d"): TJS_W("spds %%%d.*%d, %%%d"), TJS_FROM_VM_REG_ADDR(CodeArea[i+1]), TJS_FROM_VM_REG_ADDR(CodeArea[i+2]), TJS_FROM_VM_REG_ADDR(CodeArea[i+3])); if(DataArea) { com.printf(TJS_W("*%d = %ls"), TJS_FROM_VM_REG_ADDR(CodeArea[i+2]), GetValueComment(TJS_GET_VM_REG(DataArea, CodeArea[i+2])).c_str()); } size = 4; break; case VM_GPI: case VM_GPIS: // property get indirect msg.printf( CodeArea[i] == VM_GPI ? TJS_W("gpi %%%d, %%%d.%%%d"): TJS_W("gpis %%%d, %%%d.%%%d"), TJS_FROM_VM_REG_ADDR(CodeArea[i+1]), TJS_FROM_VM_REG_ADDR(CodeArea[i+2]), TJS_FROM_VM_REG_ADDR(CodeArea[i+3])); size = 4; break; case VM_SPI: case VM_SPIE: case VM_SPIS: // property set indirect msg.printf( CodeArea[i] == VM_SPI ?TJS_W("spi %%%d.%%%d, %%%d"): CodeArea[i] == VM_SPIE ?TJS_W("spie %%%d.%%%d, %%%d"): TJS_W("spis %%%d.%%%d, %%%d"), TJS_FROM_VM_REG_ADDR(CodeArea[i+1]), TJS_FROM_VM_REG_ADDR(CodeArea[i+2]), TJS_FROM_VM_REG_ADDR(CodeArea[i+3])); size = 4; break; case VM_SETP: // property set msg.printf( TJS_W("setp %%%d, %%%d"), TJS_FROM_VM_REG_ADDR(CodeArea[i+1]), TJS_FROM_VM_REG_ADDR(CodeArea[i+2])); size = 3; break; case VM_GETP: // property get msg.printf( TJS_W("getp %%%d, %%%d"), TJS_FROM_VM_REG_ADDR(CodeArea[i+1]), TJS_FROM_VM_REG_ADDR(CodeArea[i+2])); size = 3; break; case VM_DELD: case VM_TYPEOFD: // member delete direct / typeof direct msg.printf( CodeArea[i] == VM_DELD ?TJS_W("deld %%%d, %%%d.*%d"): TJS_W("typeofd %%%d, %%%d.*%d"), TJS_FROM_VM_REG_ADDR(CodeArea[i+1]), TJS_FROM_VM_REG_ADDR(CodeArea[i+2]), TJS_FROM_VM_REG_ADDR(CodeArea[i+3])); if(DataArea) { com.printf(TJS_W("*%d = %ls"), TJS_FROM_VM_REG_ADDR(CodeArea[i+3]), GetValueComment(TJS_GET_VM_REG(DataArea, CodeArea[i+3])).c_str()); } size = 4; break; case VM_DELI: case VM_TYPEOFI: // member delete indirect / typeof indirect msg.printf( CodeArea[i] == VM_DELI ?TJS_W("deli %%%d, %%%d.%%%d"): TJS_W("typeofi %%%d, %%%d.%%%d"), TJS_FROM_VM_REG_ADDR(CodeArea[i+1]), TJS_FROM_VM_REG_ADDR(CodeArea[i+2]), TJS_FROM_VM_REG_ADDR(CodeArea[i+3])); size = 4; break; case VM_SRV: // set return value msg.printf(TJS_W("srv %%%d"), TJS_FROM_VM_REG_ADDR(CodeArea[i+1])); size = 2; break; case VM_RET: // return msg.printf(TJS_W("ret")); size = 1; break; case VM_ENTRY: // enter try-protected block msg.printf(TJS_W("entry %09d, %%%d"), TJS_FROM_VM_CODE_ADDR(CodeArea[i+1]) + i, TJS_FROM_VM_REG_ADDR(CodeArea[i+2])); size = 3; break; case VM_EXTRY: // exit from try-protected block msg.printf(TJS_W("extry")); size = 1; break; case VM_THROW: msg.printf(TJS_W("throw %%%d"), TJS_FROM_VM_REG_ADDR(CodeArea[i+1])); size = 2; break; case VM_CHGTHIS: msg.printf(TJS_W("chgthis %%%d, %%%d"), TJS_FROM_VM_REG_ADDR(CodeArea[i+1]), TJS_FROM_VM_REG_ADDR(CodeArea[i+2])); size = 3; break; case VM_GLOBAL: msg.printf(TJS_W("global %%%d"), TJS_FROM_VM_REG_ADDR(CodeArea[i+1])); size = 2; break; case VM_ADDCI: msg.printf(TJS_W("addci %%%d, %%%d"), TJS_FROM_VM_REG_ADDR(CodeArea[i+1]), TJS_FROM_VM_REG_ADDR(CodeArea[i+2])); size = 3; break; case VM_REGMEMBER: msg.printf(TJS_W("regmember")); size = 1; break; case VM_DEBUGGER: msg.printf(TJS_W("debugger")); size = 1; break; default: msg.printf(TJS_W("unknown instruction %d"), CodeArea[i]); size = 1; break; } /* switch */ output_func(msg.c_str(), com.c_str(), i, CodeArea + i, size, data); // call the callback i+=size; } }