コード例 #1
0
ファイル: markov.c プロジェクト: mattwildig/markov
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;
}
コード例 #2
0
ファイル: io.c プロジェクト: soywiz/nwebp
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;
}
コード例 #3
0
ファイル: mu-cmd-find.c プロジェクト: migadu/mu
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;
}
コード例 #4
0
ファイル: mu-cmd-find.c プロジェクト: Popsch/mu
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;
}
コード例 #5
0
ファイル: stty.c プロジェクト: Crobisaur/busybox
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;
}
コード例 #6
0
ファイル: shmem_delta.c プロジェクト: neonatura/share
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);
}
コード例 #7
0
ファイル: wget.c プロジェクト: sutajiokousagi/netv-recovery
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;
}
コード例 #8
0
ファイル: tjsDisassemble.cpp プロジェクト: LonghronShen/krkrz
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;
	}

}