static int r_core_cmd_subst(RCore *core, char *cmd) {
	int ret = 0, rep = atoi (cmd), orep;
	char *cmt, *colon = NULL, *icmd = strdup (cmd);
	const char *cmdrep = NULL;
	cmd = r_str_trim_head_tail (icmd);
	// lines starting with # are ignored (never reach cmd_hash()), except #! and #?
	if (!icmd || (cmd[0] == '#' && cmd[1] != '!' && cmd[1] != '?')) {
		goto beach;
	}
	cmt = *icmd ? strchr (icmd + 1, '#'): NULL;
	if (cmt && (cmt[1] == ' ' || cmt[1] == '\t')) {
		*cmt = 0;
	}
	if (*cmd != '"') {
		if (!strchr (cmd, '\'')) { // allow | awk '{foo;bar}' // ignore ; if there's a single quote
			if ((colon = strchr (cmd, ';'))) {
				*colon = 0;
			}
		}
	} else {
		colon = NULL;
	}
	if (rep > 0) {
		while (IS_DIGIT(*cmd)) {
			cmd++;
		}
		// do not repeat null cmd
		if (!*cmd) {
			goto beach;
		}
	}
	if (rep < 1) {
		rep = 1;
	}
	// XXX if output is a pipe then we dont want to be interactive
	if (rep > 1 && r_sandbox_enable (0)) {
		eprintf ("Command repeat sugar disabled in sandbox mode (%s)\n", cmd);
		goto beach;
	} else {
		if (rep > INTERACTIVE_MAX_REP) {
			if (r_config_get_i (core->config, "scr.interactive")) {
				if (!r_cons_yesno ('n', "Are you sure to repeat this %d times? (y/N)", rep)) {
					goto beach;
				}
			}
		}
	}
	// TODO: store in core->cmdtimes to speedup ?
	cmdrep = r_config_get (core->config, "cmd.times");
	if (!cmdrep) {
		cmdrep = "";
	}
	orep = rep;

	int ocur_enabled = core->print->cur_enabled;
	while (rep-- && *cmd) {
		core->print->cur_enabled = false;
		if (ocur_enabled && core->seltab >= 0) {
			if (core->seltab == core->curtab) {
				core->print->cur_enabled = true;
			}
		}
		char *cr = strdup (cmdrep);
		core->break_loop = false;
		ret = r_core_cmd_subst_i (core, cmd, colon);
		if (ret && *cmd == 'q') {
			free (cr);
			goto beach;
		}
		if (core->break_loop) {
			break;
		}
		if (cr && *cr) {
			if (orep > 1) {
				// XXX: do not flush here, we need r_cons_push () and r_cons_pop()
				r_cons_flush ();
				// XXX: we must import register flags in C
				(void)r_core_cmd0 (core, ".dr*");
				(void)r_core_cmd0 (core, cr);
			}
		}
		free (cr);
	}
	core->print->cur_enabled = ocur_enabled;
	if (colon && colon[1]) {
		for (++colon; *colon == ';'; colon++);
		r_core_cmd_subst (core, colon);
	} else {
		if (!*icmd) {
			r_core_cmd_nullcallback (core);
		}
	}
beach:
	free (icmd);
	return ret;
}
static int r_core_cmd_subst(RCore *core, char *cmd) {
	int ret = 0, rep = atoi (cmd), orep;
	char *cmt, *colon = NULL, *icmd = strdup (cmd);
	const char *cmdrep = NULL;
	cmd = r_str_trim_head_tail (icmd);
	 
	if (!icmd || (cmd[0] == '#' && cmd[1] != '!' && cmd[1] != '?')) {
		goto beach;
	}
	cmt = *icmd ? strchr (icmd + 1, '#'): NULL;
	if (cmt && (cmt[1] == ' ' || cmt[1] == '\t')) {
		*cmt = 0;
	}
	if (*cmd != '"') {
		if (!strchr (cmd, '\'')) {  
			if ((colon = strchr (cmd, ';'))) {
				*colon = 0;
			}
		}
	} else {
		colon = NULL;
	}
	if (rep > 0) {
		while (IS_DIGIT(*cmd)) {
			cmd++;
		}
		 
		if (!*cmd) {
			goto beach;
		}
	}
	if (rep < 1) {
		rep = 1;
	}
	 
	if (rep > 1 && r_sandbox_enable (0)) {
		eprintf ("Command repeat sugar disabled in sandbox mode (%s)\n", cmd);
		goto beach;
	} else {
		if (rep > INTERACTIVE_MAX_REP) {
			if (r_config_get_i (core->config, "scr.interactive")) {
				if (!r_cons_yesno ('n', "Are you sure to repeat this %d times? (y/N)", rep)) {
					goto beach;
				}
			}
		}
	}
	 
	cmdrep = r_config_get (core->config, "cmd.times");
	if (!cmdrep) {
		cmdrep = "";
	}
	orep = rep;

	int ocur_enabled = core->print->cur_enabled;
	while (rep-- && *cmd) {
		core->print->cur_enabled = false;
		if (ocur_enabled && core->seltab >= 0) {
			if (core->seltab == core->curtab) {
				core->print->cur_enabled = true;
			}
		}
		char *cr = strdup (cmdrep);
		core->break_loop = false;
		ret = r_core_cmd_subst_i (core, cmd, colon);
		if (ret && *cmd == 'q') {
			free (cr);
			goto beach;
		}
		if (core->break_loop) {
			break;
		}
		if (cr && *cr) {
			if (orep > 1) {
				 
				r_cons_flush ();
				 
				(void)r_core_cmd0 (core, ".dr*");
				(void)r_core_cmd0 (core, cr);
			}
		}
		free (cr);
	}
	core->print->cur_enabled = ocur_enabled;
	if (colon && colon[1]) {
		for (++colon; *colon == ';'; colon++);
		r_core_cmd_subst (core, colon);
	} else {
		if (!*icmd) {
			r_core_cmd_nullcallback (core);
		}
	}
beach:
	free (icmd);
	return ret;
}