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