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