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