1 /* 2 * Copyright (c) 1989 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that the above copyright notice and this paragraph are 7 * duplicated in all such forms and that any documentation, 8 * advertising materials, and other materials related to such 9 * distribution and use acknowledge that the software was developed 10 * by the University of California, Berkeley. The name of the 11 * University may not be used to endorse or promote products derived 12 * from this software without specific prior written permission. 13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 */ 17 18 #if defined(LIBC_SCCS) && !defined(lint) 19 static char sccsid[] = "@(#)vis.c 5.1 (Berkeley) 10/13/89"; 20 #endif /* LIBC_SCCS and not lint */ 21 22 #include <sys/types.h> 23 #include <ctype.h> 24 #include <cencode.h> 25 26 #define iswhite(c) ((c)==' '||(c)=='\t'||(c)=='\n') 27 #define isoctal(c) (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7') 28 29 /* 30 * cencode 31 */ 32 33 /*VARARGS2*/ 34 char * 35 cencode(sc, flags, rachar) 36 char sc, rachar; 37 { 38 static char buff[5]; 39 register char *s = buff; 40 register u_char c = sc; 41 42 if (isgraph(c) || (!(flags&CENC_WHITE) && iswhite(c))) { 43 if (c == '\\') 44 *s++ = '\\'; 45 *s++ = c; 46 goto done; 47 } 48 *s++ = '\\'; 49 if (flags&CENC_CSTYLE) { 50 switch(c) { 51 case '\n': 52 *s++ = 'n'; 53 goto done; 54 case '\r': 55 *s++ = 'r'; 56 goto done; 57 case '\b': 58 *s++ = 'b'; 59 goto done; 60 case '\007': 61 *s++ = 'a'; 62 goto done; 63 case '\v': 64 *s++ = 'v'; 65 goto done; 66 case '\t': 67 *s++ = 't'; 68 goto done; 69 case '\f': 70 *s++ = 'f'; 71 goto done; 72 case ' ': 73 *s++ = 's'; 74 goto done; 75 case '\0': 76 *s++ = '0'; 77 if (!(flags&CENC_RACHAR) || isoctal(rachar)) { 78 *s++ = '0'; 79 *s++ = '0'; 80 } 81 goto done; 82 } 83 } 84 if ((flags&CENC_GRAPH) && (c&0177) != ' ') { 85 if (c & 0200) { 86 c &= 0177; 87 *s++ = 'M'; 88 } 89 if (iscntrl(c)) { 90 *s++ = '^'; 91 if (c == 0177) 92 *s++ = '?'; 93 else 94 *s++ = c + '@'; 95 } else { 96 *s++ = '-'; 97 *s++ = c; 98 } 99 goto done; 100 } 101 if (flags&CENC_OCTAL) { 102 if (flags&CENC_RACHAR && !isoctal(rachar)) 103 (void)sprintf(s, "%o", (int)c); 104 else 105 (void)sprintf(s, "%03o", (int)c); 106 while (*s++) 107 ; 108 goto done; 109 } 110 /* 111 * Couldn't encode. 112 */ 113 s--; 114 *s = c; 115 done: 116 *s = '\0'; 117 return(buff); 118 } 119 120 /* 121 * decode driven by state machine 122 */ 123 #define S_NORMAL 1 /* haven't seen escape char */ 124 #define S_START 2 /* start decoding special sequence */ 125 #define S_META 3 /* metachar started (M) */ 126 #define S_META1 4 /* metachar more, regular char (-) */ 127 #define S_CTRL 5 /* control char started (^) */ 128 #define S_OCTAL 6 /* octal number */ 129 130 /* 131 * 132 */ 133 cdecode(c, cp, flags) 134 char c; 135 char *cp; 136 { 137 static int state = S_NORMAL; 138 u_char buildchar; 139 int octal; 140 141 if (flags&CDEC_END) { 142 int ostate = state; 143 state = S_NORMAL; 144 if (ostate == S_OCTAL) { 145 *cp = buildchar; 146 return(CDEC_OK); 147 } else if (ostate == S_META1) { 148 /* slightly forgiving, if not wrong */ 149 *cp = ' ' | 0200; 150 return(CDEC_OK); 151 } else 152 return(ostate == S_NORMAL ? CDEC_NOCHAR : CDEC_SYNBAD); 153 } 154 155 switch (state) { 156 case S_NORMAL: 157 buildchar = 0; 158 if (c == '\\') { 159 state = S_START; 160 return(CDEC_NEEDMORE); 161 } else if (flags&CDEC_HAT && c == '^') { 162 state = S_CTRL; 163 return(CDEC_NEEDMORE); 164 } else { 165 *cp = c; 166 return(CDEC_OK); 167 } 168 break; 169 case S_START: 170 state = S_NORMAL; 171 if (c == '\\') { 172 *cp = c; 173 return(CDEC_OK); 174 } 175 if (isoctal(c)) { 176 buildchar = (c-'0'); 177 octal = 1; 178 state = S_OCTAL; 179 return(CDEC_NEEDMORE); 180 } 181 switch(c) { 182 case 'M': 183 buildchar |= 0200; 184 state = S_META; 185 return(CDEC_NEEDMORE); 186 case '^': 187 state = S_CTRL; 188 return(CDEC_NEEDMORE); 189 case 'n': 190 *cp = '\n'; 191 return(CDEC_OK); 192 case 'r': 193 *cp = '\r'; 194 return(CDEC_OK); 195 case 'b': 196 *cp = '\b'; 197 return(CDEC_OK); 198 case 'a': 199 *cp = '\007'; 200 return(CDEC_OK); 201 case 'v': 202 *cp = '\v'; 203 return(CDEC_OK); 204 case 't': 205 *cp = '\t'; 206 return(CDEC_OK); 207 case 'f': 208 *cp = '\f'; 209 return(CDEC_OK); 210 case 's': /* does anyone use this ? */ 211 *cp = ' '; 212 return(CDEC_OK); 213 case 'E': 214 *cp = '\033'; 215 return(CDEC_OK); 216 case '\n': 217 return(CDEC_NOCHAR); /* hidden newline */ 218 } 219 state = S_NORMAL; 220 return(CDEC_SYNBAD); 221 case S_META: 222 if (c == '-') 223 state = S_META1; 224 else if (c == '^') 225 state = S_CTRL; 226 else { 227 state = S_NORMAL; 228 return(CDEC_SYNBAD); 229 } 230 return(CDEC_NEEDMORE); 231 case S_META1: 232 state = S_NORMAL; 233 *cp = c | buildchar; 234 return(CDEC_OK); 235 case S_CTRL: 236 if (c == '?') 237 buildchar |= 0177; 238 else 239 buildchar |= c&037; 240 state = S_NORMAL; 241 *cp = buildchar; 242 return(CDEC_OK); 243 case S_OCTAL: 244 if (isoctal(c)) { 245 buildchar = (buildchar<<3) + (c-'0'); 246 if (++octal == 3) { 247 state = S_NORMAL; 248 *cp = buildchar; 249 return(CDEC_OK); 250 } else 251 return(CDEC_NEEDMORE); 252 } else { 253 state = S_NORMAL; 254 *cp = buildchar; 255 return(CDEC_OKPUSH); 256 } 257 } 258 } 259