144303Smarc /*- 241932Smarc * Copyright (c) 1989 The Regents of the University of California. 341932Smarc * All rights reserved. 441932Smarc * 544303Smarc * %sccs.include.redist.c% 641932Smarc */ 741932Smarc 841932Smarc #if defined(LIBC_SCCS) && !defined(lint) 9*52364Sbostic static char sccsid[] = "@(#)unvis.c 5.1 (Berkeley) 02/05/92"; 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 2744303Smarc #define isoctal(c) (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7') 2844303Smarc 2941932Smarc /* 3041932Smarc * unvis - decode characters previously encoded by vis 3141932Smarc */ 3246597Sdonn int 3341932Smarc unvis(cp, c, astate, flag) 34*52364Sbostic char *cp; 35*52364Sbostic int c, *astate, flag; 3641932Smarc { 3741932Smarc 3841932Smarc if (flag & UNVIS_END) { 3941932Smarc if (*astate == S_OCTAL2 || *astate == S_OCTAL3) { 4041932Smarc *astate = S_GROUND; 4141932Smarc return (UNVIS_VALID); 4241932Smarc } 4341932Smarc return (*astate == S_GROUND ? UNVIS_NOCHAR : UNVIS_SYNBAD); 4441932Smarc } 4541932Smarc 4641932Smarc switch (*astate) { 4741932Smarc 4841932Smarc case S_GROUND: 4941932Smarc *cp = 0; 5041932Smarc if (c == '\\') { 5141932Smarc *astate = S_START; 5241932Smarc return (0); 5341932Smarc } 5441932Smarc *cp = c; 5541932Smarc return (UNVIS_VALID); 5641932Smarc 5741932Smarc case S_START: 5841932Smarc switch(c) { 5941932Smarc case '\\': 6041932Smarc *cp = c; 6141932Smarc *astate = S_GROUND; 6241932Smarc return (UNVIS_VALID); 6341932Smarc case '0': case '1': case '2': case '3': 6441932Smarc case '4': case '5': case '6': case '7': 6541932Smarc *cp = (c - '0'); 6641932Smarc *astate = S_OCTAL2; 6741932Smarc return (0); 6841932Smarc case 'M': 6941932Smarc *cp = 0200; 7041932Smarc *astate = S_META; 7141932Smarc return (0); 7241932Smarc case '^': 7341932Smarc *astate = S_CTRL; 7441932Smarc return (0); 7541932Smarc case 'n': 7641932Smarc *cp = '\n'; 7741932Smarc *astate = S_GROUND; 7841932Smarc return (UNVIS_VALID); 7941932Smarc case 'r': 8041932Smarc *cp = '\r'; 8141932Smarc *astate = S_GROUND; 8241932Smarc return (UNVIS_VALID); 8341932Smarc case 'b': 8441932Smarc *cp = '\b'; 8541932Smarc *astate = S_GROUND; 8641932Smarc return (UNVIS_VALID); 8741932Smarc case 'a': 8841932Smarc *cp = '\007'; 8941932Smarc *astate = S_GROUND; 9041932Smarc return (UNVIS_VALID); 9141932Smarc case 'v': 9241932Smarc *cp = '\v'; 9341932Smarc *astate = S_GROUND; 9441932Smarc return (UNVIS_VALID); 9541932Smarc case 't': 9641932Smarc *cp = '\t'; 9741932Smarc *astate = S_GROUND; 9841932Smarc return (UNVIS_VALID); 9941932Smarc case 'f': 10041932Smarc *cp = '\f'; 10141932Smarc *astate = S_GROUND; 10241932Smarc return (UNVIS_VALID); 10341932Smarc case 's': 10441932Smarc *cp = ' '; 10541932Smarc *astate = S_GROUND; 10641932Smarc return (UNVIS_VALID); 10741932Smarc case 'E': 10841932Smarc *cp = '\033'; 10941932Smarc *astate = S_GROUND; 11041932Smarc return (UNVIS_VALID); 11141932Smarc case '\n': 11241932Smarc /* 11341932Smarc * hidden newline 11441932Smarc */ 11541932Smarc *astate = S_GROUND; 11641932Smarc return (UNVIS_NOCHAR); 11744303Smarc case '$': 11844303Smarc /* 11944303Smarc * hidden marker 12044303Smarc */ 12144303Smarc *astate = S_GROUND; 12244303Smarc return (UNVIS_NOCHAR); 12341932Smarc } 12441932Smarc *astate = S_GROUND; 12541932Smarc return (UNVIS_SYNBAD); 12641932Smarc 12741932Smarc case S_META: 12841932Smarc if (c == '-') 12941932Smarc *astate = S_META1; 13041932Smarc else if (c == '^') 13141932Smarc *astate = S_CTRL; 13241932Smarc else { 13341932Smarc *astate = S_GROUND; 13441932Smarc return (UNVIS_SYNBAD); 13541932Smarc } 13641932Smarc return (0); 13741932Smarc 13841932Smarc case S_META1: 13941932Smarc *astate = S_GROUND; 14041932Smarc *cp |= c; 14141932Smarc return (UNVIS_VALID); 14241932Smarc 14341932Smarc case S_CTRL: 14441932Smarc if (c == '?') 14541932Smarc *cp |= 0177; 14641932Smarc else 14741932Smarc *cp |= c & 037; 14841932Smarc *astate = S_GROUND; 14941932Smarc return (UNVIS_VALID); 15041932Smarc 15141932Smarc case S_OCTAL2: /* second possible octal digit */ 15241932Smarc if (isoctal(c)) { 15341932Smarc /* 15441932Smarc * yes - and maybe a third 15541932Smarc */ 15641932Smarc *cp = (*cp << 3) + (c - '0'); 15741932Smarc *astate = S_OCTAL3; 15841932Smarc return (0); 15941932Smarc } 16041932Smarc /* 16141932Smarc * no - done with current sequence, push back passed char 16241932Smarc */ 16341932Smarc *astate = S_GROUND; 16441932Smarc return (UNVIS_VALIDPUSH); 16541932Smarc 16641932Smarc case S_OCTAL3: /* third possible octal digit */ 16741932Smarc *astate = S_GROUND; 16841932Smarc if (isoctal(c)) { 16941932Smarc *cp = (*cp << 3) + (c - '0'); 17041932Smarc return (UNVIS_VALID); 17141932Smarc } 17241932Smarc /* 17341932Smarc * we were done, push back passed char 17441932Smarc */ 17541932Smarc return (UNVIS_VALIDPUSH); 17641932Smarc 17741932Smarc default: 17841932Smarc /* 17941932Smarc * decoder in unknown state - (probably uninitialized) 18041932Smarc */ 18144333Smarc *astate = S_GROUND; 18244333Smarc return (UNVIS_SYNBAD); 18341932Smarc } 18441932Smarc } 18541932Smarc 18641932Smarc /* 18744303Smarc * strunvis - decode src into dst 18841932Smarc * 18944303Smarc * Number of chars decoded into dst is returned, -1 on error. 19044303Smarc * Dst is null terminated. 19141932Smarc */ 19244303Smarc 19346597Sdonn int 19444303Smarc strunvis(dst, src) 19546597Sdonn register char *dst; 19646597Sdonn register const char *src; 19741932Smarc { 19844303Smarc register char c; 19941932Smarc char *start = dst; 20044333Smarc int state = 0; 20141932Smarc 20244303Smarc while (c = *src++) { 20344303Smarc again: 20444303Smarc switch (unvis(dst, c, &state, 0)) { 20544303Smarc case UNVIS_VALID: 20644303Smarc dst++; 20741932Smarc break; 20844303Smarc case UNVIS_VALIDPUSH: 20944303Smarc dst++; 21044303Smarc goto again; 21144303Smarc case 0: 21244303Smarc case UNVIS_NOCHAR: 21344303Smarc break; 21444303Smarc default: 21544303Smarc return (-1); 21644303Smarc } 21741932Smarc } 21844333Smarc if (unvis(dst, c, &state, UNVIS_END) == UNVIS_VALID) 21944333Smarc dst++; 22044303Smarc *dst = '\0'; 22141932Smarc return (dst - start); 22241932Smarc } 223