1 2 /* 3 * Copyright (c) 1989 The Regents of the University of California. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms are permitted 7 * provided that the above copyright notice and this paragraph are 8 * duplicated in all such forms and that any documentation, 9 * advertising materials, and other materials related to such 10 * distribution and use acknowledge that the software was developed 11 * by the University of California, Berkeley. The name of the 12 * University may not be used to endorse or promote products derived 13 * from this software without specific prior written permission. 14 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 15 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 17 */ 18 19 #if defined(LIBC_SCCS) && !defined(lint) 20 static char sccsid[] = "@(#)unvis.c 1.1 (Berkeley) 05/15/90"; 21 #endif /* LIBC_SCCS and not lint */ 22 23 #include <sys/types.h> 24 #include <ctype.h> 25 #include <vis.h> 26 27 /* 28 * decode driven by state machine 29 */ 30 #define S_GROUND 0 /* haven't seen escape char */ 31 #define S_START 1 /* start decoding special sequence */ 32 #define S_META 2 /* metachar started (M) */ 33 #define S_META1 3 /* metachar more, regular char (-) */ 34 #define S_CTRL 4 /* control char started (^) */ 35 #define S_OCTAL2 5 /* octal digit 2 */ 36 #define S_OCTAL3 6 /* octal digit 3 */ 37 38 /* 39 * unvis - decode characters previously encoded by vis 40 */ 41 unvis(cp, c, astate, flag) 42 u_char *cp, c; 43 int *astate, flag; 44 { 45 46 if (flag & UNVIS_END) { 47 if (*astate == S_OCTAL2 || *astate == S_OCTAL3) { 48 *astate = S_GROUND; 49 return (UNVIS_VALID); 50 } 51 return (*astate == S_GROUND ? UNVIS_NOCHAR : UNVIS_SYNBAD); 52 } 53 54 switch (*astate) { 55 56 case S_GROUND: 57 *cp = 0; 58 if (c == '\\') { 59 *astate = S_START; 60 return (0); 61 } 62 *cp = c; 63 return (UNVIS_VALID); 64 65 case S_START: 66 switch(c) { 67 case '\\': 68 *cp = c; 69 *astate = S_GROUND; 70 return (UNVIS_VALID); 71 case '0': case '1': case '2': case '3': 72 case '4': case '5': case '6': case '7': 73 *cp = (c - '0'); 74 *astate = S_OCTAL2; 75 return (0); 76 case 'M': 77 *cp = 0200; 78 *astate = S_META; 79 return (0); 80 case '^': 81 *astate = S_CTRL; 82 return (0); 83 case 'n': 84 *cp = '\n'; 85 *astate = S_GROUND; 86 return (UNVIS_VALID); 87 case 'r': 88 *cp = '\r'; 89 *astate = S_GROUND; 90 return (UNVIS_VALID); 91 case 'b': 92 *cp = '\b'; 93 *astate = S_GROUND; 94 return (UNVIS_VALID); 95 case 'a': 96 *cp = '\007'; 97 *astate = S_GROUND; 98 return (UNVIS_VALID); 99 case 'v': 100 *cp = '\v'; 101 *astate = S_GROUND; 102 return (UNVIS_VALID); 103 case 't': 104 *cp = '\t'; 105 *astate = S_GROUND; 106 return (UNVIS_VALID); 107 case 'f': 108 *cp = '\f'; 109 *astate = S_GROUND; 110 return (UNVIS_VALID); 111 case 's': 112 *cp = ' '; 113 *astate = S_GROUND; 114 return (UNVIS_VALID); 115 case 'E': 116 *cp = '\033'; 117 *astate = S_GROUND; 118 return (UNVIS_VALID); 119 case '\n': 120 /* 121 * hidden newline 122 */ 123 *astate = S_GROUND; 124 return (UNVIS_NOCHAR); 125 } 126 *astate = S_GROUND; 127 return (UNVIS_SYNBAD); 128 129 case S_META: 130 if (c == '-') 131 *astate = S_META1; 132 else if (c == '^') 133 *astate = S_CTRL; 134 else { 135 *astate = S_GROUND; 136 return (UNVIS_SYNBAD); 137 } 138 return (0); 139 140 case S_META1: 141 *astate = S_GROUND; 142 *cp |= c; 143 return (UNVIS_VALID); 144 145 case S_CTRL: 146 if (c == '?') 147 *cp |= 0177; 148 else 149 *cp |= c & 037; 150 *astate = S_GROUND; 151 return (UNVIS_VALID); 152 153 case S_OCTAL2: /* second possible octal digit */ 154 if (isoctal(c)) { 155 /* 156 * yes - and maybe a third 157 */ 158 *cp = (*cp << 3) + (c - '0'); 159 *astate = S_OCTAL3; 160 return (0); 161 } 162 /* 163 * no - done with current sequence, push back passed char 164 */ 165 *astate = S_GROUND; 166 return (UNVIS_VALIDPUSH); 167 168 case S_OCTAL3: /* third possible octal digit */ 169 *astate = S_GROUND; 170 if (isoctal(c)) { 171 *cp = (*cp << 3) + (c - '0'); 172 return (UNVIS_VALID); 173 } 174 /* 175 * we were done, push back passed char 176 */ 177 return (UNVIS_VALIDPUSH); 178 179 default: 180 /* 181 * decoder in unknown state - (probably uninitialized) 182 */ 183 return (UNVIS_ERROR); 184 } 185 } 186 187 /* 188 * strvis - visually encode characters from src into dst 189 * 190 * If len >= 0, encodes exactly len chars from src (including NULL's). 191 * Otherwise, stops before first NULL in src. In all cases, dst is 192 * NULL terminated. 193 * 194 * Dst must be 4 times the size of src to account for possible 195 * expansion. The length of dst, not including the trailing NULL, 196 * is returned. 197 */ 198 strvis(dst, src, len, flag) 199 register char *dst, *src; 200 register int len; 201 { 202 char *start = dst; 203 204 for (;;) { 205 if (len > 0) { 206 if (len-- == 0) 207 break; 208 } else if (!*src) 209 break; 210 dst = vis(dst, *src, flag, *(src+1)); 211 src++; 212 } 213 214 return (dst - start); 215 } 216