1*44303Smarc /*- 241932Smarc * Copyright (c) 1989 The Regents of the University of California. 341932Smarc * All rights reserved. 441932Smarc * 5*44303Smarc * %sccs.include.redist.c% 641932Smarc */ 741932Smarc 841932Smarc #if defined(LIBC_SCCS) && !defined(lint) 9*44303Smarc static char sccsid[] = "@(#)unvis.c 1.2 (Berkeley) 06/26/90"; 1041932Smarc #endif /* LIBC_SCCS and not lint */ 1141932Smarc 1241932Smarc #include <sys/types.h> 1341932Smarc #include <ctype.h> 1441932Smarc #include <vis.h> 1541932Smarc 1641932Smarc /* 1741932Smarc * decode driven by state machine 1841932Smarc */ 1941932Smarc #define S_GROUND 0 /* haven't seen escape char */ 2041932Smarc #define S_START 1 /* start decoding special sequence */ 2141932Smarc #define S_META 2 /* metachar started (M) */ 2241932Smarc #define S_META1 3 /* metachar more, regular char (-) */ 2341932Smarc #define S_CTRL 4 /* control char started (^) */ 2441932Smarc #define S_OCTAL2 5 /* octal digit 2 */ 2541932Smarc #define S_OCTAL3 6 /* octal digit 3 */ 2641932Smarc 27*44303Smarc #define isoctal(c) (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7') 28*44303Smarc 2941932Smarc /* 3041932Smarc * unvis - decode characters previously encoded by vis 3141932Smarc */ 3241932Smarc unvis(cp, c, astate, flag) 3341932Smarc u_char *cp, c; 3441932Smarc int *astate, flag; 3541932Smarc { 3641932Smarc 3741932Smarc if (flag & UNVIS_END) { 3841932Smarc if (*astate == S_OCTAL2 || *astate == S_OCTAL3) { 3941932Smarc *astate = S_GROUND; 4041932Smarc return (UNVIS_VALID); 4141932Smarc } 4241932Smarc return (*astate == S_GROUND ? UNVIS_NOCHAR : UNVIS_SYNBAD); 4341932Smarc } 4441932Smarc 4541932Smarc switch (*astate) { 4641932Smarc 4741932Smarc case S_GROUND: 4841932Smarc *cp = 0; 4941932Smarc if (c == '\\') { 5041932Smarc *astate = S_START; 5141932Smarc return (0); 5241932Smarc } 5341932Smarc *cp = c; 5441932Smarc return (UNVIS_VALID); 5541932Smarc 5641932Smarc case S_START: 5741932Smarc switch(c) { 5841932Smarc case '\\': 5941932Smarc *cp = c; 6041932Smarc *astate = S_GROUND; 6141932Smarc return (UNVIS_VALID); 6241932Smarc case '0': case '1': case '2': case '3': 6341932Smarc case '4': case '5': case '6': case '7': 6441932Smarc *cp = (c - '0'); 6541932Smarc *astate = S_OCTAL2; 6641932Smarc return (0); 6741932Smarc case 'M': 6841932Smarc *cp = 0200; 6941932Smarc *astate = S_META; 7041932Smarc return (0); 7141932Smarc case '^': 7241932Smarc *astate = S_CTRL; 7341932Smarc return (0); 7441932Smarc case 'n': 7541932Smarc *cp = '\n'; 7641932Smarc *astate = S_GROUND; 7741932Smarc return (UNVIS_VALID); 7841932Smarc case 'r': 7941932Smarc *cp = '\r'; 8041932Smarc *astate = S_GROUND; 8141932Smarc return (UNVIS_VALID); 8241932Smarc case 'b': 8341932Smarc *cp = '\b'; 8441932Smarc *astate = S_GROUND; 8541932Smarc return (UNVIS_VALID); 8641932Smarc case 'a': 8741932Smarc *cp = '\007'; 8841932Smarc *astate = S_GROUND; 8941932Smarc return (UNVIS_VALID); 9041932Smarc case 'v': 9141932Smarc *cp = '\v'; 9241932Smarc *astate = S_GROUND; 9341932Smarc return (UNVIS_VALID); 9441932Smarc case 't': 9541932Smarc *cp = '\t'; 9641932Smarc *astate = S_GROUND; 9741932Smarc return (UNVIS_VALID); 9841932Smarc case 'f': 9941932Smarc *cp = '\f'; 10041932Smarc *astate = S_GROUND; 10141932Smarc return (UNVIS_VALID); 10241932Smarc case 's': 10341932Smarc *cp = ' '; 10441932Smarc *astate = S_GROUND; 10541932Smarc return (UNVIS_VALID); 10641932Smarc case 'E': 10741932Smarc *cp = '\033'; 10841932Smarc *astate = S_GROUND; 10941932Smarc return (UNVIS_VALID); 11041932Smarc case '\n': 11141932Smarc /* 11241932Smarc * hidden newline 11341932Smarc */ 11441932Smarc *astate = S_GROUND; 11541932Smarc return (UNVIS_NOCHAR); 116*44303Smarc case '$': 117*44303Smarc /* 118*44303Smarc * hidden marker 119*44303Smarc */ 120*44303Smarc *astate = S_GROUND; 121*44303Smarc return (UNVIS_NOCHAR); 12241932Smarc } 12341932Smarc *astate = S_GROUND; 12441932Smarc return (UNVIS_SYNBAD); 12541932Smarc 12641932Smarc case S_META: 12741932Smarc if (c == '-') 12841932Smarc *astate = S_META1; 12941932Smarc else if (c == '^') 13041932Smarc *astate = S_CTRL; 13141932Smarc else { 13241932Smarc *astate = S_GROUND; 13341932Smarc return (UNVIS_SYNBAD); 13441932Smarc } 13541932Smarc return (0); 13641932Smarc 13741932Smarc case S_META1: 13841932Smarc *astate = S_GROUND; 13941932Smarc *cp |= c; 14041932Smarc return (UNVIS_VALID); 14141932Smarc 14241932Smarc case S_CTRL: 14341932Smarc if (c == '?') 14441932Smarc *cp |= 0177; 14541932Smarc else 14641932Smarc *cp |= c & 037; 14741932Smarc *astate = S_GROUND; 14841932Smarc return (UNVIS_VALID); 14941932Smarc 15041932Smarc case S_OCTAL2: /* second possible octal digit */ 15141932Smarc if (isoctal(c)) { 15241932Smarc /* 15341932Smarc * yes - and maybe a third 15441932Smarc */ 15541932Smarc *cp = (*cp << 3) + (c - '0'); 15641932Smarc *astate = S_OCTAL3; 15741932Smarc return (0); 15841932Smarc } 15941932Smarc /* 16041932Smarc * no - done with current sequence, push back passed char 16141932Smarc */ 16241932Smarc *astate = S_GROUND; 16341932Smarc return (UNVIS_VALIDPUSH); 16441932Smarc 16541932Smarc case S_OCTAL3: /* third possible octal digit */ 16641932Smarc *astate = S_GROUND; 16741932Smarc if (isoctal(c)) { 16841932Smarc *cp = (*cp << 3) + (c - '0'); 16941932Smarc return (UNVIS_VALID); 17041932Smarc } 17141932Smarc /* 17241932Smarc * we were done, push back passed char 17341932Smarc */ 17441932Smarc return (UNVIS_VALIDPUSH); 17541932Smarc 17641932Smarc default: 17741932Smarc /* 17841932Smarc * decoder in unknown state - (probably uninitialized) 17941932Smarc */ 18041932Smarc return (UNVIS_ERROR); 18141932Smarc } 18241932Smarc } 18341932Smarc 18441932Smarc /* 185*44303Smarc * strunvis - decode src into dst 18641932Smarc * 187*44303Smarc * Number of chars decoded into dst is returned, -1 on error. 188*44303Smarc * Dst is null terminated. 18941932Smarc */ 190*44303Smarc 191*44303Smarc strunvis(dst, src) 19241932Smarc register char *dst, *src; 19341932Smarc { 194*44303Smarc register char c; 19541932Smarc char *start = dst; 196*44303Smarc int state; 19741932Smarc 198*44303Smarc while (c = *src++) { 199*44303Smarc again: 200*44303Smarc switch (unvis(dst, c, &state, 0)) { 201*44303Smarc case UNVIS_VALID: 202*44303Smarc dst++; 20341932Smarc break; 204*44303Smarc case UNVIS_VALIDPUSH: 205*44303Smarc dst++; 206*44303Smarc goto again; 207*44303Smarc case 0: 208*44303Smarc case UNVIS_NOCHAR: 209*44303Smarc break; 210*44303Smarc default: 211*44303Smarc return (-1); 212*44303Smarc } 21341932Smarc } 214*44303Smarc *dst = '\0'; 21541932Smarc return (dst - start); 21641932Smarc } 217