170 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			170 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
/* tr - translate characters		Author: Michiel Huisjes */
 | 
						|
/* Usage: tr [-cds] [string1 [string2]]
 | 
						|
 *	c: take complement of string1
 | 
						|
 *	d: delete input characters coded string1
 | 
						|
 *	s: squeeze multiple output characters of string2 into one character
 | 
						|
 */
 | 
						|
 | 
						|
#define BUFFER_SIZE	1024
 | 
						|
#define ASCII		0377
 | 
						|
 | 
						|
typedef char BOOL;
 | 
						|
#define TRUE	1
 | 
						|
#define FALSE	0
 | 
						|
 | 
						|
#define NIL_PTR		((char *) 0)
 | 
						|
 | 
						|
BOOL com_fl, del_fl, sq_fl;
 | 
						|
 | 
						|
unsigned char output[BUFFER_SIZE], input[BUFFER_SIZE];
 | 
						|
unsigned char vector[ASCII + 1];
 | 
						|
BOOL invec[ASCII + 1], outvec[ASCII + 1];
 | 
						|
 | 
						|
short in_index, out_index;
 | 
						|
 | 
						|
#include <sys/types.h>
 | 
						|
#include <string.h>
 | 
						|
#include <stdlib.h>
 | 
						|
#include <unistd.h>
 | 
						|
 | 
						|
_PROTOTYPE(int main, (int argc, char **argv));
 | 
						|
_PROTOTYPE(void convert, (void));
 | 
						|
_PROTOTYPE(void map, (unsigned char *string1, unsigned char *string2));
 | 
						|
_PROTOTYPE(void expand, (char *arg, unsigned char *buffer));
 | 
						|
_PROTOTYPE(void complement, (unsigned char *buffer));
 | 
						|
 | 
						|
int main(argc, argv)
 | 
						|
int argc;
 | 
						|
char *argv[];
 | 
						|
{
 | 
						|
  register unsigned char *ptr;
 | 
						|
  int index = 1;
 | 
						|
  short 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:
 | 
						|
			write(2,"Usage: tr [-cds] [string1 [string2]].\n", 38);
 | 
						|
			exit(1);
 | 
						|
		}
 | 
						|
	}
 | 
						|
	index++;
 | 
						|
  }
 | 
						|
  for (i = 0; i <= ASCII; i++) {
 | 
						|
	vector[i] = i;
 | 
						|
	invec[i] = outvec[i] = FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  if (argv[index] != NIL_PTR) {
 | 
						|
	expand(argv[index++], input);
 | 
						|
	if (com_fl) complement(input);
 | 
						|
	if (argv[index] != NIL_PTR) expand(argv[index], output);
 | 
						|
	if (argv[index] != NIL_PTR) map(input, output);
 | 
						|
	for (ptr = input; *ptr; ptr++) invec[*ptr] = TRUE;
 | 
						|
	for (ptr = output; *ptr; ptr++) outvec[*ptr] = TRUE;
 | 
						|
  }
 | 
						|
  convert();
 | 
						|
  return(0);
 | 
						|
}
 | 
						|
 | 
						|
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, BUFFER_SIZE)) <= 0) {
 | 
						|
			if (write(1, (char *)output, out_index) != out_index)
 | 
						|
				write(2, "Bad write\n", 10);
 | 
						|
			exit(0);
 | 
						|
		}
 | 
						|
		in_index = 0;
 | 
						|
	}
 | 
						|
	c = input[in_index++];
 | 
						|
	coded = vector[c];
 | 
						|
	if (del_fl && invec[c]) continue;
 | 
						|
	if (sq_fl && last == coded && outvec[coded]) continue;
 | 
						|
	output[out_index++] = last = coded;
 | 
						|
	if (out_index == BUFFER_SIZE) {
 | 
						|
		if (write(1, (char *)output, out_index) != out_index) {
 | 
						|
			write(2, "Bad write\n", 10);
 | 
						|
			exit(1);
 | 
						|
		}
 | 
						|
		out_index = 0;
 | 
						|
	}
 | 
						|
  }
 | 
						|
 | 
						|
  /* NOTREACHED */
 | 
						|
}
 | 
						|
 | 
						|
void map(string1, string2)
 | 
						|
register unsigned char *string1, *string2;
 | 
						|
{
 | 
						|
  unsigned char last;
 | 
						|
 | 
						|
  while (*string1) {
 | 
						|
	if (*string2 == '\0')
 | 
						|
		vector[*string1] = last;
 | 
						|
	else
 | 
						|
		vector[*string1] = last = *string2++;
 | 
						|
	string1++;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void expand(arg, buffer)
 | 
						|
register char *arg;
 | 
						|
register unsigned char *buffer;
 | 
						|
{
 | 
						|
  int i, ac;
 | 
						|
 | 
						|
  while (*arg) {
 | 
						|
	if (*arg == '\\') {
 | 
						|
		arg++;
 | 
						|
		i = ac = 0;
 | 
						|
		if (*arg >= '0' && *arg <= '7') {
 | 
						|
			do {
 | 
						|
				ac = (ac << 3) + *arg++ - '0';
 | 
						|
				i++;
 | 
						|
			} while (i < 4 && *arg >= '0' && *arg <= '7');
 | 
						|
			*buffer++ = ac;
 | 
						|
		} else if (*arg != '\0')
 | 
						|
			*buffer++ = *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++;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void complement(buffer)
 | 
						|
unsigned char *buffer;
 | 
						|
{
 | 
						|
  register unsigned char *ptr;
 | 
						|
  register short i, index;
 | 
						|
  unsigned char conv[ASCII + 2];
 | 
						|
 | 
						|
  index = 0;
 | 
						|
  for (i = 1; i <= ASCII; i++) {
 | 
						|
	for (ptr = buffer; *ptr; ptr++)
 | 
						|
		if (*ptr == i) break;
 | 
						|
	if (*ptr == '\0') conv[index++] = i & ASCII;
 | 
						|
  }
 | 
						|
  conv[index] = '\0';
 | 
						|
  strcpy((char *)buffer, (char *)conv);
 | 
						|
}
 |