/* vi: set sw=4 ts=4: */
/*
 * Mini tr implementation for busybox
 *
 * Copyright (c) Michiel Huisjes
 *
 * This version of tr is adapted from Minix tr and was modified 
 * by Erik Andersen <andersee@debian.org> to be used in busybox.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 * 
 * Original copyright notice is retained at the end of this file.
 */

#include "busybox.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#define BB_DECLARE_EXTERN
#define bb_need_write_error
#include "messages.c"

#ifdef TRUE
#undef TRUE
#undef FALSE
#define TRUE	1
#define FALSE	0
#endif

#define ASCII		0377

/* some glabals shared across this file */
static char com_fl, del_fl, sq_fl;
static unsigned char output[BUFSIZ], input[BUFSIZ];
static unsigned char vector[ASCII + 1];
static char invec[ASCII + 1], outvec[ASCII + 1];
static short in_index, out_index;


static void convert()
{
	short read_chars = 0;
	short c, coded;
	short last = -1;

	for (;;) {
		if (in_index == read_chars) {
			if ((read_chars = read(0, (char *) input, BUFSIZ)) <= 0) {
				if (write(1, (char *) output, out_index) != out_index)
					write(2, write_error, strlen(write_error));
				exit(0);
			}
			in_index = 0;
		}
		c = input[in_index++];
		coded = vector[c];
		if (del_fl && invec[c])
			continue;
		if (sq_fl && last == coded && (invec[c] || outvec[coded]))
			continue;
		output[out_index++] = last = coded;
		if (out_index == BUFSIZ) {
			if (write(1, (char *) output, out_index) != out_index) {
				write(2, write_error, strlen(write_error));
				exit(1);
			}
			out_index = 0;
		}
	}

	/* NOTREACHED */
}

static void map(register unsigned char *string1, unsigned int string1_len,
		register unsigned char *string2, unsigned int string2_len)
{
	unsigned char last = '0';
	unsigned int i, j;

	for (j = 0, i = 0; i < string1_len; i++) {
		if (string2_len <= j)
			vector[string1[i]] = last;
		else
			vector[string1[i]] = last = string2[j++];
	}
}

static unsigned int expand(char *arg, register unsigned char *buffer)
{
	unsigned char *buffer_start = buffer;
	int i, ac;

	while (*arg) {
		if (*arg == '\\') {
			arg++;
			*buffer++ = process_escape_sequence(&arg);
		} else if (*arg == '[') {
			arg++;
			i = *arg++;
			if (*arg++ != '-') {
				*buffer++ = '[';
				arg -= 2;
				continue;
			}
			ac = *arg++;
			while (i <= ac)
				*buffer++ = i++;
			arg++;				/* Skip ']' */
		} else
			*buffer++ = *arg++;
	}

	return (buffer - buffer_start);
}

static int complement(unsigned char *buffer, int buffer_len)
{
	register short i, j, index;
	char conv[ASCII + 2];

	index = 0;
	for (i = 0; i <= ASCII; i++) {
		for (j = 0; j < buffer_len; j++)
			if (buffer[j] == i)
				break;
		if (j == buffer_len)
			conv[index++] = i & ASCII;
	}
	memcpy(buffer, conv, index);
	return index;
}

extern int tr_main(int argc, char **argv)
{
	register unsigned char *ptr;
	int output_length=0, input_length;
	int index = 1;
	int i;

	if (argc > 1 && argv[index][0] == '-') {
		for (ptr = (unsigned char *) &argv[index][1]; *ptr; ptr++) {
			switch (*ptr) {
			case 'c':
				com_fl = TRUE;
				break;
			case 'd':
				del_fl = TRUE;
				break;
			case 's':
				sq_fl = TRUE;
				break;
			default:
				usage(tr_usage);
			}
		}
		index++;
	}
	for (i = 0; i <= ASCII; i++) {
		vector[i] = i;
		invec[i] = outvec[i] = FALSE;
	}

	if (argv[index] != NULL) {
		input_length = expand(argv[index++], input);
		if (com_fl)
			input_length = complement(input, input_length);
		if (argv[index] != NULL) {
			if (*argv[index] == '\0')
				fatalError("STRING2 cannot be empty\n");
			output_length = expand(argv[index], output);
			map(input, input_length, output, output_length);
		}
		for (i = 0; i < input_length; i++)
			invec[input[i]] = TRUE;
		for (i = 0; i < output_length; i++)
			outvec[output[i]] = TRUE;
	}
	convert();
	return (0);
}

/*
 * Copyright (c) 1987,1997, Prentice Hall
 * All rights reserved.
 * 
 * Redistribution and use of the MINIX operating system in source and
 * binary forms, with or without modification, are permitted provided
 * that the following conditions are met:
 * 
 * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 * 
 * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following
 * disclaimer in the documentation and/or other materials provided
 * with the distribution.
 * 
 * Neither the name of Prentice Hall nor the names of the software
 * authors or contributors may be used to endorse or promote
 * products derived from this software without specific prior
 * written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS, AUTHORS, AND
 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL PRENTICE HALL OR ANY AUTHORS OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

