Beispiel #1
0
static void do_subst_w_backrefs(const char *line, const char *replace)
{
	int i,j;

	/* go through the replacement string */
	for (i = 0; replace[i]; i++) {
		/* if we find a backreference (\1, \2, etc.) print the backref'ed * text */
		if (replace[i] == '\\' && replace[i+1]>'0' && replace[i+1]<='9') {
			int backref=replace[++i]-'0';

			/* print out the text held in regmatch[backref] */
			if(regmatch[backref].rm_so != -1)
				for (j = regmatch[backref].rm_so; j < regmatch[backref].rm_eo; j++)
					pipe_putc(line[j]);
		}

		/* if we find a backslash escaped character, print the character */
		else if (replace[i] == '\\') pipe_putc(replace[++i]);

		/* if we find an unescaped '&' print out the whole matched text. */
		else if (replace[i] == '&')
			for (j = regmatch[0].rm_so; j < regmatch[0].rm_eo; j++)
				pipe_putc(line[j]);
		/* Otherwise just output the character. */
		else pipe_putc(replace[i]);
	}
}
Beispiel #2
0
size_t pipe_write(struct robject *self, rp_t source, uint8_t *buffer, size_t size, off_t offset) {
	struct pipe *pipe;
	size_t i;

	pipe = robject_data(self, "pipe");
	
	for (i = 0; i < size; i++) {
		pipe_putc(pipe, buffer[i]);
	}

	return size;
}
Beispiel #3
0
static void do_subst_w_backrefs(char *line, char *replace)
{
	int i, j;

	/* go through the replacement string */
	for (i = 0; replace[i]; i++) {
		/* if we find a backreference (\1, \2, etc.) print the backref'ed text */
		if (replace[i] == '\\') {
			unsigned backref = replace[++i] - '0';
			if (backref <= 9) {
				/* print out the text held in G.regmatch[backref] */
				if (G.regmatch[backref].rm_so != -1) {
					j = G.regmatch[backref].rm_so;
					while (j < G.regmatch[backref].rm_eo)
						pipe_putc(line[j++]);
				}
				continue;
			}
			/* I _think_ it is impossible to get '\' to be
			 * the last char in replace string. Thus we don't check
			 * for replace[i] == NUL. (counterexample anyone?) */
			/* if we find a backslash escaped character, print the character */
			pipe_putc(replace[i]);
			continue;
		}
		/* if we find an unescaped '&' print out the whole matched text. */
		if (replace[i] == '&') {
			j = G.regmatch[0].rm_so;
			while (j < G.regmatch[0].rm_eo)
				pipe_putc(line[j++]);
			continue;
		}
		/* Otherwise just output the character. */
		pipe_putc(replace[i]);
	}
}
Beispiel #4
0
static int do_subst_command(sed_cmd_t *sed_cmd, char **line_p)
{
	char *line = *line_p;
	unsigned match_count = 0;
	bool altered = 0;
	bool prev_match_empty = 1;
	bool tried_at_eol = 0;
	regex_t *current_regex;

	current_regex = sed_cmd->sub_match;
	/* Handle empty regex. */
	if (!current_regex) {
		current_regex = G.previous_regex_ptr;
		if (!current_regex)
			bb_error_msg_and_die("no previous regexp");
	}
	G.previous_regex_ptr = current_regex;

	/* Find the first match */
	dbg("matching '%s'", line);
	if (REG_NOMATCH == regexec(current_regex, line, 10, G.regmatch, 0)) {
		dbg("no match");
		return 0;
	}
	dbg("match");

	/* Initialize temporary output buffer. */
	G.pipeline.buf = xmalloc(PIPE_GROW);
	G.pipeline.len = PIPE_GROW;
	G.pipeline.idx = 0;

	/* Now loop through, substituting for matches */
	do {
		int start = G.regmatch[0].rm_so;
		int end = G.regmatch[0].rm_eo;
		int i;

		match_count++;

		/* If we aren't interested in this match, output old line to
		 * end of match and continue */
		if (sed_cmd->which_match
		 && (sed_cmd->which_match != match_count)
		) {
			for (i = 0; i < end; i++)
				pipe_putc(*line++);
			/* Null match? Print one more char */
			if (start == end && *line)
				pipe_putc(*line++);
			goto next;
		}

		/* Print everything before the match */
		for (i = 0; i < start; i++)
			pipe_putc(line[i]);

		/* Then print the substitution string,
		 * unless we just matched empty string after non-empty one.
		 * Example: string "cccd", pattern "c*", repl "R":
		 * result is "RdR", not "RRdR": first match "ccc",
		 * second is "" before "d", third is "" after "d".
		 * Second match is NOT replaced!
		 */
		if (prev_match_empty || start != 0 || start != end) {
			//dbg("%d %d %d", prev_match_empty, start, end);
			dbg("inserting replacement at %d in '%s'", start, line);
			do_subst_w_backrefs(line, sed_cmd->string);
			/* Flag that something has changed */
			altered = 1;
		} else {
			dbg("NOT inserting replacement at %d in '%s'", start, line);
		}

		/* If matched string is empty (f.e. "c*" pattern),
		 * copy verbatim one char after it before attempting more matches
		 */
		prev_match_empty = (start == end);
		if (prev_match_empty) {
			if (!line[end]) {
				tried_at_eol = 1;
			} else {
				pipe_putc(line[end]);
				end++;
			}
		}

		/* Advance past the match */
		dbg("line += %d", end);
		line += end;

		/* if we're not doing this globally, get out now */
		if (sed_cmd->which_match != 0)
			break;
 next:
		/* Exit if we are at EOL and already tried matching at it */
		if (*line == '\0') {
			if (tried_at_eol)
				break;
			tried_at_eol = 1;
		}

//maybe (end ? REG_NOTBOL : 0) instead of unconditional REG_NOTBOL?
	} while (regexec(current_regex, line, 10, G.regmatch, REG_NOTBOL) != REG_NOMATCH);

	/* Copy rest of string into output pipeline */
	while (1) {
		char c = *line++;
		pipe_putc(c);
		if (c == '\0')
			break;
	}

	free(*line_p);
	*line_p = G.pipeline.buf;
	return altered;
}
Beispiel #5
0
static int do_subst_command(sed_cmd_t *sed_cmd, char **line)
{
	char *oldline = *line;
	int altered = 0;
	unsigned match_count = 0;
	regex_t *current_regex;

	/* Handle empty regex. */
	if (sed_cmd->sub_match == NULL) {
		current_regex = G.previous_regex_ptr;
		if (!current_regex)
			bb_error_msg_and_die("no previous regexp");
	} else
		G.previous_regex_ptr = current_regex = sed_cmd->sub_match;

	/* Find the first match */
	if (REG_NOMATCH == regexec(current_regex, oldline, 10, G.regmatch, 0))
		return 0;

	/* Initialize temporary output buffer. */
	G.pipeline.buf = xmalloc(PIPE_GROW);
	G.pipeline.len = PIPE_GROW;
	G.pipeline.idx = 0;

	/* Now loop through, substituting for matches */
	do {
		int i;

		/* Work around bug in glibc regexec, demonstrated by:
		   echo " a.b" | busybox sed 's [^ .]* x g'
		   The match_count check is so not to break
		   echo "hi" | busybox sed 's/^/!/g' */
		if (!G.regmatch[0].rm_so && !G.regmatch[0].rm_eo && match_count) {
			pipe_putc(*oldline++);
			continue;
		}

		match_count++;

		/* If we aren't interested in this match, output old line to
		   end of match and continue */
		if (sed_cmd->which_match
		 && (sed_cmd->which_match != match_count)
		) {
			for (i = 0; i < G.regmatch[0].rm_eo; i++)
				pipe_putc(*oldline++);
			continue;
		}

		/* print everything before the match */
		for (i = 0; i < G.regmatch[0].rm_so; i++)
			pipe_putc(oldline[i]);

		/* then print the substitution string */
		do_subst_w_backrefs(oldline, sed_cmd->string);

		/* advance past the match */
		oldline += G.regmatch[0].rm_eo;
		/* flag that something has changed */
		altered++;

		/* if we're not doing this globally, get out now */
		if (sed_cmd->which_match)
			break;
	} while (*oldline && (regexec(current_regex, oldline, 10, G.regmatch, 0) != REG_NOMATCH));

	/* Copy rest of string into output pipeline */

	while (*oldline)
		pipe_putc(*oldline++);
	pipe_putc(0);

	free(*line);
	*line = G.pipeline.buf;
	return altered;
}