Home | History | Annotate | Download | only in tr
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License, Version 1.0 only
      6  * (the "License").  You may not use this file except in compliance
      7  * with the License.
      8  *
      9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
     10  * or http://www.opensolaris.org/os/licensing.
     11  * See the License for the specific language governing permissions
     12  * and limitations under the License.
     13  *
     14  * When distributing Covered Code, include this CDDL HEADER in each
     15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     16  * If applicable, add the following below this CDDL HEADER, with the
     17  * fields enclosed by brackets "[]" replaced with your own identifying
     18  * information: Portions Copyright [yyyy] [name of copyright owner]
     19  *
     20  * CDDL HEADER END
     21  */
     22 /*
     23  * Copyright 1988 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
     28 /*	  All Rights Reserved  	*/
     29 
     30 /*
     31  * University Copyright- Copyright (c) 1982, 1986, 1988
     32  * The Regents of the University of California
     33  * All Rights Reserved
     34  *
     35  * University Acknowledgment- Portions of this document are derived from
     36  * software developed by the University of California, Berkeley, and its
     37  * contributors.
     38  */
     39 
     40 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     41 
     42 #include <stdio.h>
     43 
     44 /* tr - transliterate data stream */
     45 int	dflag	= 0;
     46 int	sflag	= 0;
     47 int	cflag = 0;
     48 int	save	= 0;
     49 char	code[256];
     50 char	squeez[256];
     51 char	vect[256];
     52 struct string { int last, max; char *p; } string1, string2;
     53 
     54 int
     55 main(int argc, char **argv)
     56 {
     57 	int i;
     58 	int j;
     59 	int c, d;
     60 	char *compl;
     61 	int lastd;
     62 
     63 	string1.last = string2.last = 0;
     64 	string1.max = string2.max = 0;
     65 	string1.p = string2.p = "";
     66 
     67 	if(--argc>0) {
     68 		argv++;
     69 		if(*argv[0]=='-'&&argv[0][1]!=0) {
     70 			while(*++argv[0])
     71 				switch(*argv[0]) {
     72 				case 'c':
     73 					cflag++;
     74 					continue;
     75 				case 'd':
     76 					dflag++;
     77 					continue;
     78 				case 's':
     79 					sflag++;
     80 					continue;
     81 				}
     82 			argc--;
     83 			argv++;
     84 		}
     85 	}
     86 	if(argc>0) string1.p = argv[0];
     87 	if(argc>1) string2.p = argv[1];
     88 	for(i=0; i<256; i++)
     89 		code[i] = vect[i] = 0;
     90 	if(cflag) {
     91 		while(c = next(&string1))
     92 			vect[c&0377] = 1;
     93 		j = 0;
     94 		for(i=1; i<256; i++)
     95 			if(vect[i]==0) vect[j++] = i;
     96 		vect[j] = 0;
     97 		compl = vect;
     98 	}
     99 	for(i=0; i<256; i++)
    100 		squeez[i] = 0;
    101 	lastd = 0;
    102 	for(;;){
    103 		if(cflag) c = *compl++;
    104 		else c = next(&string1);
    105 		if(c==0) break;
    106 		d = next(&string2);
    107 		if(d==0) d = lastd;
    108 		else lastd = d;
    109 		squeez[d&0377] = 1;
    110 		code[c&0377] = dflag?1:d;
    111 	}
    112 	while(d = next(&string2))
    113 		squeez[d&0377] = 1;
    114 	squeez[0] = 1;
    115 	for(i=0;i<256;i++) {
    116 		if(code[i]==0) code[i] = i;
    117 		else if(dflag) code[i] = 0;
    118 	}
    119 
    120 	clearerr(stdout);
    121 	while((c=getc(stdin)) != EOF ) {
    122 		if(c == 0) continue;
    123 		if(c = code[c&0377]&0377)
    124 			if(!sflag || c!=save || !squeez[c&0377]) {
    125 				(void)putchar(save = c);
    126 				if(ferror(stdout))
    127 					exit(1);
    128 			}
    129 	}
    130 	return (0);
    131 }
    132 
    133 int
    134 next(struct string *s)
    135 {
    136 
    137 again:
    138 	if(s->max) {
    139 		if(s->last++ < s->max)
    140 			return(s->last);
    141 		s->max = s->last = 0;
    142 	}
    143 	if(s->last && *s->p=='-') {
    144 		(void)nextc(s);
    145 		s->max = nextc(s);
    146 		if(s->max==0) {
    147 			s->p--;
    148 			return('-');
    149 		}
    150 		if(s->max < s->last)  {
    151 			s->last = s->max-1;
    152 			return('-');
    153 		}
    154 		goto again;
    155 	}
    156 	return(s->last = nextc(s));
    157 }
    158 
    159 int
    160 nextc(struct string *s)
    161 {
    162 	int c, i, n;
    163 
    164 	c = *s->p++;
    165 	if(c=='\\') {
    166 		i = n = 0;
    167 		while(i<3 && (c = *s->p)>='0' && c<='7') {
    168 			n = n*8 + c - '0';
    169 			i++;
    170 			s->p++;
    171 		}
    172 		if(i>0) c = n;
    173 		else c = *s->p++;
    174 	}
    175 	if(c==0) *--s->p = 0;
    176 	return(c&0377);
    177 }
    178