Vendor import of NetBSD's (un)vis(3) as of 2012-10-05
This commit is contained in:
commit
5f6a0f033f
244
unvis.3
Normal file
244
unvis.3
Normal file
@ -0,0 +1,244 @@
|
||||
.\" $NetBSD: unvis.3,v 1.23 2011/03/17 14:06:29 wiz Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1989, 1991, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. Neither the name of the University nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" @(#)unvis.3 8.2 (Berkeley) 12/11/93
|
||||
.\"
|
||||
.Dd March 12, 2011
|
||||
.Dt UNVIS 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm unvis ,
|
||||
.Nm strunvis
|
||||
.Nd decode a visual representation of characters
|
||||
.Sh LIBRARY
|
||||
.Lb libc
|
||||
.Sh SYNOPSIS
|
||||
.In vis.h
|
||||
.Ft int
|
||||
.Fn unvis "char *cp" "int c" "int *astate" "int flag"
|
||||
.Ft int
|
||||
.Fn strunvis "char *dst" "const char *src"
|
||||
.Ft int
|
||||
.Fn strnunvis "char *dst" "size_t dlen" "const char *src"
|
||||
.Ft int
|
||||
.Fn strunvisx "char *dst" "const char *src" "int flag"
|
||||
.Ft int
|
||||
.Fn strnunvisx "char *dst" "size_t dlen" "const char *src" "int flag"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Fn unvis ,
|
||||
.Fn strunvis
|
||||
and
|
||||
.Fn strunvisx
|
||||
functions
|
||||
are used to decode a visual representation of characters, as produced
|
||||
by the
|
||||
.Xr vis 3
|
||||
function, back into
|
||||
the original form.
|
||||
.Pp
|
||||
The
|
||||
.Fn unvis
|
||||
function is called with successive characters in
|
||||
.Ar c
|
||||
until a valid sequence is recognized, at which time the decoded
|
||||
character is available at the character pointed to by
|
||||
.Ar cp .
|
||||
.Pp
|
||||
The
|
||||
.Fn strunvis
|
||||
function decodes the characters pointed to by
|
||||
.Ar src
|
||||
into the buffer pointed to by
|
||||
.Ar dst .
|
||||
The
|
||||
.Fn strunvis
|
||||
function simply copies
|
||||
.Ar src
|
||||
to
|
||||
.Ar dst ,
|
||||
decoding any escape sequences along the way,
|
||||
and returns the number of characters placed into
|
||||
.Ar dst ,
|
||||
or \-1 if an
|
||||
invalid escape sequence was detected.
|
||||
The size of
|
||||
.Ar dst
|
||||
should be equal to the size of
|
||||
.Ar src
|
||||
(that is, no expansion takes place during decoding).
|
||||
.Pp
|
||||
The
|
||||
.Fn strunvisx
|
||||
function does the same as the
|
||||
.Fn strunvis
|
||||
function,
|
||||
but it allows you to add a flag that specifies the style the string
|
||||
.Ar src
|
||||
is encoded with.
|
||||
Currently, the supported flags are:
|
||||
.Dv VIS_HTTPSTYLE
|
||||
and
|
||||
.Dv VIS_MIMESTYLE .
|
||||
.Pp
|
||||
The
|
||||
.Fn unvis
|
||||
function implements a state machine that can be used to decode an
|
||||
arbitrary stream of bytes.
|
||||
All state associated with the bytes being decoded is stored outside the
|
||||
.Fn unvis
|
||||
function (that is, a pointer to the state is passed in), so
|
||||
calls decoding different streams can be freely intermixed.
|
||||
To start decoding a stream of bytes, first initialize an integer to zero.
|
||||
Call
|
||||
.Fn unvis
|
||||
with each successive byte, along with a pointer
|
||||
to this integer, and a pointer to a destination character.
|
||||
The
|
||||
.Fn unvis
|
||||
function has several return codes that must be handled properly.
|
||||
They are:
|
||||
.Bl -tag -width UNVIS_VALIDPUSH
|
||||
.It Li \&0 (zero)
|
||||
Another character is necessary; nothing has been recognized yet.
|
||||
.It Dv UNVIS_VALID
|
||||
A valid character has been recognized and is available at the location
|
||||
pointed to by cp.
|
||||
.It Dv UNVIS_VALIDPUSH
|
||||
A valid character has been recognized and is available at the location
|
||||
pointed to by cp; however, the character currently passed in should
|
||||
be passed in again.
|
||||
.It Dv UNVIS_NOCHAR
|
||||
A valid sequence was detected, but no character was produced.
|
||||
This return code is necessary to indicate a logical break between characters.
|
||||
.It Dv UNVIS_SYNBAD
|
||||
An invalid escape sequence was detected, or the decoder is in an unknown state.
|
||||
The decoder is placed into the starting state.
|
||||
.El
|
||||
.Pp
|
||||
When all bytes in the stream have been processed, call
|
||||
.Fn unvis
|
||||
one more time with flag set to
|
||||
.Dv UNVIS_END
|
||||
to extract any remaining character (the character passed in is ignored).
|
||||
.Pp
|
||||
The
|
||||
.Ar flag
|
||||
argument is also used to specify the encoding style of the source.
|
||||
If set to
|
||||
.Dv VIS_HTTPSTYLE
|
||||
or
|
||||
.Dv VIS_HTTP1808 ,
|
||||
.Fn unvis
|
||||
will decode URI strings as specified in RFC 1808.
|
||||
If set to
|
||||
.Dv VIS_HTTP1866 ,
|
||||
.Fn unvis
|
||||
will decode URI strings as specified in RFC 1866.
|
||||
If set to
|
||||
.Dv VIS_MIMESTYLE ,
|
||||
.Fn unvis
|
||||
will decode MIME Quoted-Printable strings as specified in RFC 2045.
|
||||
If set to
|
||||
.Dv VIS_NOESCAPE ,
|
||||
.Fn unvis
|
||||
will not decode \e quoted characters.
|
||||
.Pp
|
||||
The following code fragment illustrates a proper use of
|
||||
.Fn unvis .
|
||||
.Bd -literal -offset indent
|
||||
int state = 0;
|
||||
char out;
|
||||
|
||||
while ((ch = getchar()) != EOF) {
|
||||
again:
|
||||
switch(unvis(\*[Am]out, ch, \*[Am]state, 0)) {
|
||||
case 0:
|
||||
case UNVIS_NOCHAR:
|
||||
break;
|
||||
case UNVIS_VALID:
|
||||
(void)putchar(out);
|
||||
break;
|
||||
case UNVIS_VALIDPUSH:
|
||||
(void)putchar(out);
|
||||
goto again;
|
||||
case UNVIS_SYNBAD:
|
||||
errx(EXIT_FAILURE, "Bad character sequence!");
|
||||
}
|
||||
}
|
||||
if (unvis(\*[Am]out, '\e0', \*[Am]state, UNVIS_END) == UNVIS_VALID)
|
||||
(void)putchar(out);
|
||||
.Ed
|
||||
.Sh ERRORS
|
||||
The functions
|
||||
.Fn strunvis ,
|
||||
.Fn strnunvis ,
|
||||
.Fn strunvisx ,
|
||||
and
|
||||
.Fn strnunvisx
|
||||
will return \-1 on error and set
|
||||
.Va errno
|
||||
to:
|
||||
.Bl -tag -width Er
|
||||
.It Bq Er EINVAL
|
||||
An invalid escape sequence was detected, or the decoder is in an unknown state.
|
||||
.El
|
||||
.Pp
|
||||
In addition the functions
|
||||
.Fn strnunvis
|
||||
and
|
||||
.Fn strnunvisx
|
||||
will can also set
|
||||
.Va errno
|
||||
on error to:
|
||||
.Bl -tag -width Er
|
||||
.It Bq Er ENOSPC
|
||||
Not enough space to perform the conversion.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr unvis 1 ,
|
||||
.Xr vis 1 ,
|
||||
.Xr vis 3
|
||||
.Rs
|
||||
.%A R. Fielding
|
||||
.%T Relative Uniform Resource Locators
|
||||
.%O RFC1808
|
||||
.Re
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Fn unvis
|
||||
function
|
||||
first appeared in
|
||||
.Bx 4.4 .
|
||||
The
|
||||
.Fn strnunvis
|
||||
and
|
||||
.Fn strnunvisx
|
||||
functions appeared in
|
||||
.Nx 6.0 .
|
553
unvis.c
Normal file
553
unvis.c
Normal file
@ -0,0 +1,553 @@
|
||||
/* $NetBSD: unvis.c,v 1.39 2012/03/13 21:13:37 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)unvis.c 8.1 (Berkeley) 6/4/93";
|
||||
#else
|
||||
__RCSID("$NetBSD: unvis.c,v 1.39 2012/03/13 21:13:37 christos Exp $");
|
||||
#endif
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include "namespace.h"
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <vis.h>
|
||||
|
||||
#ifdef __weak_alias
|
||||
__weak_alias(strnunvisx,_strnunvisx)
|
||||
#endif
|
||||
|
||||
#if !HAVE_VIS
|
||||
/*
|
||||
* decode driven by state machine
|
||||
*/
|
||||
#define S_GROUND 0 /* haven't seen escape char */
|
||||
#define S_START 1 /* start decoding special sequence */
|
||||
#define S_META 2 /* metachar started (M) */
|
||||
#define S_META1 3 /* metachar more, regular char (-) */
|
||||
#define S_CTRL 4 /* control char started (^) */
|
||||
#define S_OCTAL2 5 /* octal digit 2 */
|
||||
#define S_OCTAL3 6 /* octal digit 3 */
|
||||
#define S_HEX 7 /* mandatory hex digit */
|
||||
#define S_HEX1 8 /* http hex digit */
|
||||
#define S_HEX2 9 /* http hex digit 2 */
|
||||
#define S_MIME1 10 /* mime hex digit 1 */
|
||||
#define S_MIME2 11 /* mime hex digit 2 */
|
||||
#define S_EATCRNL 12 /* mime eating CRNL */
|
||||
#define S_AMP 13 /* seen & */
|
||||
#define S_NUMBER 14 /* collecting number */
|
||||
#define S_STRING 15 /* collecting string */
|
||||
|
||||
#define isoctal(c) (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7')
|
||||
#define xtod(c) (isdigit(c) ? (c - '0') : ((tolower(c) - 'a') + 10))
|
||||
#define XTOD(c) (isdigit(c) ? (c - '0') : ((c - 'A') + 10))
|
||||
|
||||
/*
|
||||
* RFC 1866
|
||||
*/
|
||||
static const struct nv {
|
||||
const char *name;
|
||||
uint8_t value;
|
||||
} nv[] = {
|
||||
{ "AElig", 198 }, /* capital AE diphthong (ligature) */
|
||||
{ "Aacute", 193 }, /* capital A, acute accent */
|
||||
{ "Acirc", 194 }, /* capital A, circumflex accent */
|
||||
{ "Agrave", 192 }, /* capital A, grave accent */
|
||||
{ "Aring", 197 }, /* capital A, ring */
|
||||
{ "Atilde", 195 }, /* capital A, tilde */
|
||||
{ "Auml", 196 }, /* capital A, dieresis or umlaut mark */
|
||||
{ "Ccedil", 199 }, /* capital C, cedilla */
|
||||
{ "ETH", 208 }, /* capital Eth, Icelandic */
|
||||
{ "Eacute", 201 }, /* capital E, acute accent */
|
||||
{ "Ecirc", 202 }, /* capital E, circumflex accent */
|
||||
{ "Egrave", 200 }, /* capital E, grave accent */
|
||||
{ "Euml", 203 }, /* capital E, dieresis or umlaut mark */
|
||||
{ "Iacute", 205 }, /* capital I, acute accent */
|
||||
{ "Icirc", 206 }, /* capital I, circumflex accent */
|
||||
{ "Igrave", 204 }, /* capital I, grave accent */
|
||||
{ "Iuml", 207 }, /* capital I, dieresis or umlaut mark */
|
||||
{ "Ntilde", 209 }, /* capital N, tilde */
|
||||
{ "Oacute", 211 }, /* capital O, acute accent */
|
||||
{ "Ocirc", 212 }, /* capital O, circumflex accent */
|
||||
{ "Ograve", 210 }, /* capital O, grave accent */
|
||||
{ "Oslash", 216 }, /* capital O, slash */
|
||||
{ "Otilde", 213 }, /* capital O, tilde */
|
||||
{ "Ouml", 214 }, /* capital O, dieresis or umlaut mark */
|
||||
{ "THORN", 222 }, /* capital THORN, Icelandic */
|
||||
{ "Uacute", 218 }, /* capital U, acute accent */
|
||||
{ "Ucirc", 219 }, /* capital U, circumflex accent */
|
||||
{ "Ugrave", 217 }, /* capital U, grave accent */
|
||||
{ "Uuml", 220 }, /* capital U, dieresis or umlaut mark */
|
||||
{ "Yacute", 221 }, /* capital Y, acute accent */
|
||||
{ "aacute", 225 }, /* small a, acute accent */
|
||||
{ "acirc", 226 }, /* small a, circumflex accent */
|
||||
{ "acute", 180 }, /* acute accent */
|
||||
{ "aelig", 230 }, /* small ae diphthong (ligature) */
|
||||
{ "agrave", 224 }, /* small a, grave accent */
|
||||
{ "amp", 38 }, /* ampersand */
|
||||
{ "aring", 229 }, /* small a, ring */
|
||||
{ "atilde", 227 }, /* small a, tilde */
|
||||
{ "auml", 228 }, /* small a, dieresis or umlaut mark */
|
||||
{ "brvbar", 166 }, /* broken (vertical) bar */
|
||||
{ "ccedil", 231 }, /* small c, cedilla */
|
||||
{ "cedil", 184 }, /* cedilla */
|
||||
{ "cent", 162 }, /* cent sign */
|
||||
{ "copy", 169 }, /* copyright sign */
|
||||
{ "curren", 164 }, /* general currency sign */
|
||||
{ "deg", 176 }, /* degree sign */
|
||||
{ "divide", 247 }, /* divide sign */
|
||||
{ "eacute", 233 }, /* small e, acute accent */
|
||||
{ "ecirc", 234 }, /* small e, circumflex accent */
|
||||
{ "egrave", 232 }, /* small e, grave accent */
|
||||
{ "eth", 240 }, /* small eth, Icelandic */
|
||||
{ "euml", 235 }, /* small e, dieresis or umlaut mark */
|
||||
{ "frac12", 189 }, /* fraction one-half */
|
||||
{ "frac14", 188 }, /* fraction one-quarter */
|
||||
{ "frac34", 190 }, /* fraction three-quarters */
|
||||
{ "gt", 62 }, /* greater than */
|
||||
{ "iacute", 237 }, /* small i, acute accent */
|
||||
{ "icirc", 238 }, /* small i, circumflex accent */
|
||||
{ "iexcl", 161 }, /* inverted exclamation mark */
|
||||
{ "igrave", 236 }, /* small i, grave accent */
|
||||
{ "iquest", 191 }, /* inverted question mark */
|
||||
{ "iuml", 239 }, /* small i, dieresis or umlaut mark */
|
||||
{ "laquo", 171 }, /* angle quotation mark, left */
|
||||
{ "lt", 60 }, /* less than */
|
||||
{ "macr", 175 }, /* macron */
|
||||
{ "micro", 181 }, /* micro sign */
|
||||
{ "middot", 183 }, /* middle dot */
|
||||
{ "nbsp", 160 }, /* no-break space */
|
||||
{ "not", 172 }, /* not sign */
|
||||
{ "ntilde", 241 }, /* small n, tilde */
|
||||
{ "oacute", 243 }, /* small o, acute accent */
|
||||
{ "ocirc", 244 }, /* small o, circumflex accent */
|
||||
{ "ograve", 242 }, /* small o, grave accent */
|
||||
{ "ordf", 170 }, /* ordinal indicator, feminine */
|
||||
{ "ordm", 186 }, /* ordinal indicator, masculine */
|
||||
{ "oslash", 248 }, /* small o, slash */
|
||||
{ "otilde", 245 }, /* small o, tilde */
|
||||
{ "ouml", 246 }, /* small o, dieresis or umlaut mark */
|
||||
{ "para", 182 }, /* pilcrow (paragraph sign) */
|
||||
{ "plusmn", 177 }, /* plus-or-minus sign */
|
||||
{ "pound", 163 }, /* pound sterling sign */
|
||||
{ "quot", 34 }, /* double quote */
|
||||
{ "raquo", 187 }, /* angle quotation mark, right */
|
||||
{ "reg", 174 }, /* registered sign */
|
||||
{ "sect", 167 }, /* section sign */
|
||||
{ "shy", 173 }, /* soft hyphen */
|
||||
{ "sup1", 185 }, /* superscript one */
|
||||
{ "sup2", 178 }, /* superscript two */
|
||||
{ "sup3", 179 }, /* superscript three */
|
||||
{ "szlig", 223 }, /* small sharp s, German (sz ligature) */
|
||||
{ "thorn", 254 }, /* small thorn, Icelandic */
|
||||
{ "times", 215 }, /* multiply sign */
|
||||
{ "uacute", 250 }, /* small u, acute accent */
|
||||
{ "ucirc", 251 }, /* small u, circumflex accent */
|
||||
{ "ugrave", 249 }, /* small u, grave accent */
|
||||
{ "uml", 168 }, /* umlaut (dieresis) */
|
||||
{ "uuml", 252 }, /* small u, dieresis or umlaut mark */
|
||||
{ "yacute", 253 }, /* small y, acute accent */
|
||||
{ "yen", 165 }, /* yen sign */
|
||||
{ "yuml", 255 }, /* small y, dieresis or umlaut mark */
|
||||
};
|
||||
|
||||
/*
|
||||
* unvis - decode characters previously encoded by vis
|
||||
*/
|
||||
int
|
||||
unvis(char *cp, int c, int *astate, int flag)
|
||||
{
|
||||
unsigned char uc = (unsigned char)c;
|
||||
unsigned char st, ia, is, lc;
|
||||
|
||||
/*
|
||||
* Bottom 8 bits of astate hold the state machine state.
|
||||
* Top 8 bits hold the current character in the http 1866 nv string decoding
|
||||
*/
|
||||
#define GS(a) ((a) & 0xff)
|
||||
#define SS(a, b) (((uint32_t)(a) << 24) | (b))
|
||||
#define GI(a) ((uint32_t)(a) >> 24)
|
||||
|
||||
_DIAGASSERT(cp != NULL);
|
||||
_DIAGASSERT(astate != NULL);
|
||||
st = GS(*astate);
|
||||
|
||||
if (flag & UNVIS_END) {
|
||||
switch (st) {
|
||||
case S_OCTAL2:
|
||||
case S_OCTAL3:
|
||||
case S_HEX2:
|
||||
*astate = SS(0, S_GROUND);
|
||||
return UNVIS_VALID;
|
||||
case S_GROUND:
|
||||
return UNVIS_NOCHAR;
|
||||
default:
|
||||
return UNVIS_SYNBAD;
|
||||
}
|
||||
}
|
||||
|
||||
switch (st) {
|
||||
|
||||
case S_GROUND:
|
||||
*cp = 0;
|
||||
if ((flag & VIS_NOESCAPE) == 0 && c == '\\') {
|
||||
*astate = SS(0, S_START);
|
||||
return UNVIS_NOCHAR;
|
||||
}
|
||||
if ((flag & VIS_HTTP1808) && c == '%') {
|
||||
*astate = SS(0, S_HEX1);
|
||||
return UNVIS_NOCHAR;
|
||||
}
|
||||
if ((flag & VIS_HTTP1866) && c == '&') {
|
||||
*astate = SS(0, S_AMP);
|
||||
return UNVIS_NOCHAR;
|
||||
}
|
||||
if ((flag & VIS_MIMESTYLE) && c == '=') {
|
||||
*astate = SS(0, S_MIME1);
|
||||
return UNVIS_NOCHAR;
|
||||
}
|
||||
*cp = c;
|
||||
return UNVIS_VALID;
|
||||
|
||||
case S_START:
|
||||
switch(c) {
|
||||
case '\\':
|
||||
*cp = c;
|
||||
*astate = SS(0, S_GROUND);
|
||||
return UNVIS_VALID;
|
||||
case '0': case '1': case '2': case '3':
|
||||
case '4': case '5': case '6': case '7':
|
||||
*cp = (c - '0');
|
||||
*astate = SS(0, S_OCTAL2);
|
||||
return UNVIS_NOCHAR;
|
||||
case 'M':
|
||||
*cp = (char)0200;
|
||||
*astate = SS(0, S_META);
|
||||
return UNVIS_NOCHAR;
|
||||
case '^':
|
||||
*astate = SS(0, S_CTRL);
|
||||
return UNVIS_NOCHAR;
|
||||
case 'n':
|
||||
*cp = '\n';
|
||||
*astate = SS(0, S_GROUND);
|
||||
return UNVIS_VALID;
|
||||
case 'r':
|
||||
*cp = '\r';
|
||||
*astate = SS(0, S_GROUND);
|
||||
return UNVIS_VALID;
|
||||
case 'b':
|
||||
*cp = '\b';
|
||||
*astate = SS(0, S_GROUND);
|
||||
return UNVIS_VALID;
|
||||
case 'a':
|
||||
*cp = '\007';
|
||||
*astate = SS(0, S_GROUND);
|
||||
return UNVIS_VALID;
|
||||
case 'v':
|
||||
*cp = '\v';
|
||||
*astate = SS(0, S_GROUND);
|
||||
return UNVIS_VALID;
|
||||
case 't':
|
||||
*cp = '\t';
|
||||
*astate = SS(0, S_GROUND);
|
||||
return UNVIS_VALID;
|
||||
case 'f':
|
||||
*cp = '\f';
|
||||
*astate = SS(0, S_GROUND);
|
||||
return UNVIS_VALID;
|
||||
case 's':
|
||||
*cp = ' ';
|
||||
*astate = SS(0, S_GROUND);
|
||||
return UNVIS_VALID;
|
||||
case 'E':
|
||||
*cp = '\033';
|
||||
*astate = SS(0, S_GROUND);
|
||||
return UNVIS_VALID;
|
||||
case 'x':
|
||||
*astate = SS(0, S_HEX);
|
||||
return UNVIS_NOCHAR;
|
||||
case '\n':
|
||||
/*
|
||||
* hidden newline
|
||||
*/
|
||||
*astate = SS(0, S_GROUND);
|
||||
return UNVIS_NOCHAR;
|
||||
case '$':
|
||||
/*
|
||||
* hidden marker
|
||||
*/
|
||||
*astate = SS(0, S_GROUND);
|
||||
return UNVIS_NOCHAR;
|
||||
}
|
||||
goto bad;
|
||||
|
||||
case S_META:
|
||||
if (c == '-')
|
||||
*astate = SS(0, S_META1);
|
||||
else if (c == '^')
|
||||
*astate = SS(0, S_CTRL);
|
||||
else
|
||||
goto bad;
|
||||
return UNVIS_NOCHAR;
|
||||
|
||||
case S_META1:
|
||||
*astate = SS(0, S_GROUND);
|
||||
*cp |= c;
|
||||
return UNVIS_VALID;
|
||||
|
||||
case S_CTRL:
|
||||
if (c == '?')
|
||||
*cp |= 0177;
|
||||
else
|
||||
*cp |= c & 037;
|
||||
*astate = SS(0, S_GROUND);
|
||||
return UNVIS_VALID;
|
||||
|
||||
case S_OCTAL2: /* second possible octal digit */
|
||||
if (isoctal(uc)) {
|
||||
/*
|
||||
* yes - and maybe a third
|
||||
*/
|
||||
*cp = (*cp << 3) + (c - '0');
|
||||
*astate = SS(0, S_OCTAL3);
|
||||
return UNVIS_NOCHAR;
|
||||
}
|
||||
/*
|
||||
* no - done with current sequence, push back passed char
|
||||
*/
|
||||
*astate = SS(0, S_GROUND);
|
||||
return UNVIS_VALIDPUSH;
|
||||
|
||||
case S_OCTAL3: /* third possible octal digit */
|
||||
*astate = SS(0, S_GROUND);
|
||||
if (isoctal(uc)) {
|
||||
*cp = (*cp << 3) + (c - '0');
|
||||
return UNVIS_VALID;
|
||||
}
|
||||
/*
|
||||
* we were done, push back passed char
|
||||
*/
|
||||
return UNVIS_VALIDPUSH;
|
||||
|
||||
case S_HEX:
|
||||
if (!isxdigit(uc))
|
||||
goto bad;
|
||||
/*FALLTHROUGH*/
|
||||
case S_HEX1:
|
||||
if (isxdigit(uc)) {
|
||||
*cp = xtod(uc);
|
||||
*astate = SS(0, S_HEX2);
|
||||
return UNVIS_NOCHAR;
|
||||
}
|
||||
/*
|
||||
* no - done with current sequence, push back passed char
|
||||
*/
|
||||
*astate = SS(0, S_GROUND);
|
||||
return UNVIS_VALIDPUSH;
|
||||
|
||||
case S_HEX2:
|
||||
*astate = S_GROUND;
|
||||
if (isxdigit(uc)) {
|
||||
*cp = xtod(uc) | (*cp << 4);
|
||||
return UNVIS_VALID;
|
||||
}
|
||||
return UNVIS_VALIDPUSH;
|
||||
|
||||
case S_MIME1:
|
||||
if (uc == '\n' || uc == '\r') {
|
||||
*astate = SS(0, S_EATCRNL);
|
||||
return UNVIS_NOCHAR;
|
||||
}
|
||||
if (isxdigit(uc) && (isdigit(uc) || isupper(uc))) {
|
||||
*cp = XTOD(uc);
|
||||
*astate = SS(0, S_MIME2);
|
||||
return UNVIS_NOCHAR;
|
||||
}
|
||||
goto bad;
|
||||
|
||||
case S_MIME2:
|
||||
if (isxdigit(uc) && (isdigit(uc) || isupper(uc))) {
|
||||
*astate = SS(0, S_GROUND);
|
||||
*cp = XTOD(uc) | (*cp << 4);
|
||||
return UNVIS_VALID;
|
||||
}
|
||||
goto bad;
|
||||
|
||||
case S_EATCRNL:
|
||||
switch (uc) {
|
||||
case '\r':
|
||||
case '\n':
|
||||
return UNVIS_NOCHAR;
|
||||
case '=':
|
||||
*astate = SS(0, S_MIME1);
|
||||
return UNVIS_NOCHAR;
|
||||
default:
|
||||
*cp = uc;
|
||||
*astate = SS(0, S_GROUND);
|
||||
return UNVIS_VALID;
|
||||
}
|
||||
|
||||
case S_AMP:
|
||||
*cp = 0;
|
||||
if (uc == '#') {
|
||||
*astate = SS(0, S_NUMBER);
|
||||
return UNVIS_NOCHAR;
|
||||
}
|
||||
*astate = SS(0, S_STRING);
|
||||
/*FALLTHROUGH*/
|
||||
|
||||
case S_STRING:
|
||||
ia = *cp; /* index in the array */
|
||||
is = GI(*astate); /* index in the string */
|
||||
lc = is == 0 ? 0 : nv[ia].name[is - 1]; /* last character */
|
||||
|
||||
if (uc == ';')
|
||||
uc = '\0';
|
||||
|
||||
for (; ia < __arraycount(nv); ia++) {
|
||||
if (is != 0 && nv[ia].name[is - 1] != lc)
|
||||
goto bad;
|
||||
if (nv[ia].name[is] == uc)
|
||||
break;
|
||||
}
|
||||
|
||||
if (ia == __arraycount(nv))
|
||||
goto bad;
|
||||
|
||||
if (uc != 0) {
|
||||
*cp = ia;
|
||||
*astate = SS(is + 1, S_STRING);
|
||||
return UNVIS_NOCHAR;
|
||||
}
|
||||
|
||||
*cp = nv[ia].value;
|
||||
*astate = SS(0, S_GROUND);
|
||||
return UNVIS_VALID;
|
||||
|
||||
case S_NUMBER:
|
||||
if (uc == ';')
|
||||
return UNVIS_VALID;
|
||||
if (!isdigit(uc))
|
||||
goto bad;
|
||||
*cp += (*cp * 10) + uc - '0';
|
||||
return UNVIS_NOCHAR;
|
||||
|
||||
default:
|
||||
bad:
|
||||
/*
|
||||
* decoder in unknown state - (probably uninitialized)
|
||||
*/
|
||||
*astate = SS(0, S_GROUND);
|
||||
return UNVIS_SYNBAD;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* strnunvisx - decode src into dst
|
||||
*
|
||||
* Number of chars decoded into dst is returned, -1 on error.
|
||||
* Dst is null terminated.
|
||||
*/
|
||||
|
||||
int
|
||||
strnunvisx(char *dst, size_t dlen, const char *src, int flag)
|
||||
{
|
||||
char c;
|
||||
char t = '\0', *start = dst;
|
||||
int state = 0;
|
||||
|
||||
_DIAGASSERT(src != NULL);
|
||||
_DIAGASSERT(dst != NULL);
|
||||
#define CHECKSPACE() \
|
||||
do { \
|
||||
if (dlen-- == 0) { \
|
||||
errno = ENOSPC; \
|
||||
return -1; \
|
||||
} \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
while ((c = *src++) != '\0') {
|
||||
again:
|
||||
switch (unvis(&t, c, &state, flag)) {
|
||||
case UNVIS_VALID:
|
||||
CHECKSPACE();
|
||||
*dst++ = t;
|
||||
break;
|
||||
case UNVIS_VALIDPUSH:
|
||||
CHECKSPACE();
|
||||
*dst++ = t;
|
||||
goto again;
|
||||
case 0:
|
||||
case UNVIS_NOCHAR:
|
||||
break;
|
||||
case UNVIS_SYNBAD:
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
default:
|
||||
_DIAGASSERT(/*CONSTCOND*/0);
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (unvis(&t, c, &state, UNVIS_END) == UNVIS_VALID) {
|
||||
CHECKSPACE();
|
||||
*dst++ = t;
|
||||
}
|
||||
CHECKSPACE();
|
||||
*dst = '\0';
|
||||
return (int)(dst - start);
|
||||
}
|
||||
|
||||
int
|
||||
strunvisx(char *dst, const char *src, int flag)
|
||||
{
|
||||
return strnunvisx(dst, (size_t)~0, src, flag);
|
||||
}
|
||||
|
||||
int
|
||||
strunvis(char *dst, const char *src)
|
||||
{
|
||||
return strnunvisx(dst, (size_t)~0, src, 0);
|
||||
}
|
||||
|
||||
int
|
||||
strnunvis(char *dst, size_t dlen, const char *src)
|
||||
{
|
||||
return strnunvisx(dst, dlen, src, 0);
|
||||
}
|
||||
#endif
|
441
vis.3
Normal file
441
vis.3
Normal file
@ -0,0 +1,441 @@
|
||||
.\" $NetBSD: vis.3,v 1.27 2011/05/17 07:10:39 joerg Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1989, 1991, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. Neither the name of the University nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" @(#)vis.3 8.1 (Berkeley) 6/9/93
|
||||
.\"
|
||||
.Dd March 12, 2011
|
||||
.Dt VIS 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm vis ,
|
||||
.Nm nvis ,
|
||||
.Nm strvis ,
|
||||
.Nm strnvis ,
|
||||
.Nm strvisx ,
|
||||
.Nm strnvisx ,
|
||||
.Nm svis ,
|
||||
.Nm snvis ,
|
||||
.Nm strsvis ,
|
||||
.Nm strsnvis ,
|
||||
.Nm strsvisx
|
||||
.Nm strsnvisx
|
||||
.Nd visually encode characters
|
||||
.Sh LIBRARY
|
||||
.Lb libc
|
||||
.Sh SYNOPSIS
|
||||
.In vis.h
|
||||
.Ft char *
|
||||
.Fn vis "char *dst" "int c" "int flag" "int nextc"
|
||||
.Ft char *
|
||||
.Fn nvis "char *dst" "size_t dlen" "int c" "int flag" "int nextc"
|
||||
.Ft int
|
||||
.Fn strvis "char *dst" "const char *src" "int flag"
|
||||
.Ft int
|
||||
.Fn strnvis "char *dst" "size_t dlen" "const char *src" "int flag"
|
||||
.Ft int
|
||||
.Fn strvisx "char *dst" "const char *src" "size_t len" "int flag"
|
||||
.Ft int
|
||||
.Fn strnvisx "char *dst" "size_t dlen" "const char *src" "size_t len" "int flag"
|
||||
.Ft char *
|
||||
.Fn svis "char *dst" "int c" "int flag" "int nextc" "const char *extra"
|
||||
.Ft char *
|
||||
.Fn snvis "char *dst" "size_t dlen" "int c" "int flag" "int nextc" "const char *extra"
|
||||
.Ft int
|
||||
.Fn strsvis "char *dst" "const char *src" "int flag" "const char *extra"
|
||||
.Ft int
|
||||
.Fn strsnvis "char *dst" "size_t dlen" "const char *src" "int flag" "const char *extra"
|
||||
.Ft int
|
||||
.Fn strsvisx "char *dst" "const char *src" "size_t len" "int flag" "const char *extra"
|
||||
.Ft int
|
||||
.Fn strsnvisx "char *dst" "size_t dlen" "const char *src" "size_t len" "int flag" "const char *extra"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Fn vis
|
||||
function
|
||||
copies into
|
||||
.Fa dst
|
||||
a string which represents the character
|
||||
.Fa c .
|
||||
If
|
||||
.Fa c
|
||||
needs no encoding, it is copied in unaltered.
|
||||
The string is null terminated, and a pointer to the end of the string is
|
||||
returned.
|
||||
The maximum length of any encoding is four
|
||||
characters (not including the trailing
|
||||
.Dv NUL ) ;
|
||||
thus, when
|
||||
encoding a set of characters into a buffer, the size of the buffer should
|
||||
be four times the number of characters encoded, plus one for the trailing
|
||||
.Dv NUL .
|
||||
The flag parameter is used for altering the default range of
|
||||
characters considered for encoding and for altering the visual
|
||||
representation.
|
||||
The additional character,
|
||||
.Fa nextc ,
|
||||
is only used when selecting the
|
||||
.Dv VIS_CSTYLE
|
||||
encoding format (explained below).
|
||||
.Pp
|
||||
The
|
||||
.Fn strvis ,
|
||||
.Fn strnvis ,
|
||||
.Fn strvisx ,
|
||||
and
|
||||
.Fn strnvisx
|
||||
functions copy into
|
||||
.Fa dst
|
||||
a visual representation of
|
||||
the string
|
||||
.Fa src .
|
||||
The
|
||||
.Fn strvis
|
||||
and
|
||||
.Fn strnvis
|
||||
functions encode characters from
|
||||
.Fa src
|
||||
up to the
|
||||
first
|
||||
.Dv NUL .
|
||||
The
|
||||
.Fn strvisx
|
||||
and
|
||||
.Fn strnvisx
|
||||
functions encode exactly
|
||||
.Fa len
|
||||
characters from
|
||||
.Fa src
|
||||
(this
|
||||
is useful for encoding a block of data that may contain
|
||||
.Dv NUL Ns 's ) .
|
||||
Both forms
|
||||
.Dv NUL
|
||||
terminate
|
||||
.Fa dst .
|
||||
The size of
|
||||
.Fa dst
|
||||
must be four times the number
|
||||
of characters encoded from
|
||||
.Fa src
|
||||
(plus one for the
|
||||
.Dv NUL ) .
|
||||
Both
|
||||
forms return the number of characters in dst (not including
|
||||
the trailing
|
||||
.Dv NUL ) .
|
||||
The
|
||||
.Dq n
|
||||
versions of the functions also take an additional argument
|
||||
.Fa dlen
|
||||
that indicates the length of the
|
||||
.Fa dst
|
||||
buffer.
|
||||
If
|
||||
.Fa dlen
|
||||
is not large enough to fix the converted string then the
|
||||
.Fn strnvis
|
||||
and
|
||||
.Fn strnvisx
|
||||
functions return \-1 and set
|
||||
.Va errno
|
||||
to
|
||||
.Dv ENOSPC .
|
||||
.Pp
|
||||
The functions
|
||||
.Fn svis ,
|
||||
.Fn snvis ,
|
||||
.Fn strsvis ,
|
||||
.Fn strsnvis ,
|
||||
.Fn strsvisx ,
|
||||
and
|
||||
.Fn strsnvisx
|
||||
correspond to
|
||||
.Fn vis ,
|
||||
.Fn nvis ,
|
||||
.Fn strvis ,
|
||||
.Fn strnvis ,
|
||||
.Fn strvisx ,
|
||||
and
|
||||
.Fn strnvisx
|
||||
but have an additional argument
|
||||
.Fa extra ,
|
||||
pointing to a
|
||||
.Dv NUL
|
||||
terminated list of characters.
|
||||
These characters will be copied encoded or backslash-escaped into
|
||||
.Fa dst .
|
||||
These functions are useful e.g. to remove the special meaning
|
||||
of certain characters to shells.
|
||||
.Pp
|
||||
The encoding is a unique, invertible representation composed entirely of
|
||||
graphic characters; it can be decoded back into the original form using
|
||||
the
|
||||
.Xr unvis 3 ,
|
||||
.Xr strunvis 3
|
||||
or
|
||||
.Xr strnunvis 3
|
||||
functions.
|
||||
.Pp
|
||||
There are two parameters that can be controlled: the range of
|
||||
characters that are encoded (applies only to
|
||||
.Fn vis ,
|
||||
.Fn nvis ,
|
||||
.Fn strvis ,
|
||||
.Fn strnvis ,
|
||||
.Fn strvisx ,
|
||||
and
|
||||
.Fn strnvisx ) ,
|
||||
and the type of representation used.
|
||||
By default, all non-graphic characters,
|
||||
except space, tab, and newline are encoded.
|
||||
(See
|
||||
.Xr isgraph 3 . )
|
||||
The following flags
|
||||
alter this:
|
||||
.Bl -tag -width VIS_WHITEX
|
||||
.It Dv VIS_SP
|
||||
Also encode space.
|
||||
.It Dv VIS_TAB
|
||||
Also encode tab.
|
||||
.It Dv VIS_NL
|
||||
Also encode newline.
|
||||
.It Dv VIS_WHITE
|
||||
Synonym for
|
||||
.Dv VIS_SP
|
||||
\&|
|
||||
.Dv VIS_TAB
|
||||
\&|
|
||||
.Dv VIS_NL .
|
||||
.It Dv VIS_SAFE
|
||||
Only encode "unsafe" characters.
|
||||
Unsafe means control characters which may cause common terminals to perform
|
||||
unexpected functions.
|
||||
Currently this form allows space, tab, newline, backspace, bell, and
|
||||
return - in addition to all graphic characters - unencoded.
|
||||
.El
|
||||
.Pp
|
||||
(The above flags have no effect for
|
||||
.Fn svis ,
|
||||
.Fn snvis ,
|
||||
.Fn strsvis ,
|
||||
.Fn strsnvis ,
|
||||
.Fn strsvisx ,
|
||||
and
|
||||
.Fn strsnvisx .
|
||||
When using these functions, place all graphic characters to be
|
||||
encoded in an array pointed to by
|
||||
.Fa extra .
|
||||
In general, the backslash character should be included in this array, see the
|
||||
warning on the use of the
|
||||
.Dv VIS_NOSLASH
|
||||
flag below).
|
||||
.Pp
|
||||
There are four forms of encoding.
|
||||
All forms use the backslash character
|
||||
.Ql \e
|
||||
to introduce a special
|
||||
sequence; two backslashes are used to represent a real backslash,
|
||||
except
|
||||
.Dv VIS_HTTPSTYLE
|
||||
that uses
|
||||
.Ql % ,
|
||||
or
|
||||
.Dv VIS_MIMESTYLE
|
||||
that uses
|
||||
.Ql = .
|
||||
These are the visual formats:
|
||||
.Bl -tag -width VIS_CSTYLE
|
||||
.It (default)
|
||||
Use an
|
||||
.Ql M
|
||||
to represent meta characters (characters with the 8th
|
||||
bit set), and use caret
|
||||
.Ql ^
|
||||
to represent control characters see
|
||||
.Pf ( Xr iscntrl 3 ) .
|
||||
The following formats are used:
|
||||
.Bl -tag -width xxxxx
|
||||
.It Dv \e^C
|
||||
Represents the control character
|
||||
.Ql C .
|
||||
Spans characters
|
||||
.Ql \e000
|
||||
through
|
||||
.Ql \e037 ,
|
||||
and
|
||||
.Ql \e177
|
||||
(as
|
||||
.Ql \e^? ) .
|
||||
.It Dv \eM-C
|
||||
Represents character
|
||||
.Ql C
|
||||
with the 8th bit set.
|
||||
Spans characters
|
||||
.Ql \e241
|
||||
through
|
||||
.Ql \e376 .
|
||||
.It Dv \eM^C
|
||||
Represents control character
|
||||
.Ql C
|
||||
with the 8th bit set.
|
||||
Spans characters
|
||||
.Ql \e200
|
||||
through
|
||||
.Ql \e237 ,
|
||||
and
|
||||
.Ql \e377
|
||||
(as
|
||||
.Ql \eM^? ) .
|
||||
.It Dv \e040
|
||||
Represents
|
||||
.Tn ASCII
|
||||
space.
|
||||
.It Dv \e240
|
||||
Represents Meta-space.
|
||||
.El
|
||||
.Pp
|
||||
.It Dv VIS_CSTYLE
|
||||
Use C-style backslash sequences to represent standard non-printable
|
||||
characters.
|
||||
The following sequences are used to represent the indicated characters:
|
||||
.Bd -unfilled -offset indent
|
||||
.Li \ea Tn - BEL No (007)
|
||||
.Li \eb Tn - BS No (010)
|
||||
.Li \ef Tn - NP No (014)
|
||||
.Li \en Tn - NL No (012)
|
||||
.Li \er Tn - CR No (015)
|
||||
.Li \es Tn - SP No (040)
|
||||
.Li \et Tn - HT No (011)
|
||||
.Li \ev Tn - VT No (013)
|
||||
.Li \e0 Tn - NUL No (000)
|
||||
.Ed
|
||||
.Pp
|
||||
When using this format, the nextc parameter is looked at to determine
|
||||
if a
|
||||
.Dv NUL
|
||||
character can be encoded as
|
||||
.Ql \e0
|
||||
instead of
|
||||
.Ql \e000 .
|
||||
If
|
||||
.Fa nextc
|
||||
is an octal digit, the latter representation is used to
|
||||
avoid ambiguity.
|
||||
.It Dv VIS_OCTAL
|
||||
Use a three digit octal sequence.
|
||||
The form is
|
||||
.Ql \eddd
|
||||
where
|
||||
.Em d
|
||||
represents an octal digit.
|
||||
.It Dv VIS_HTTPSTYLE
|
||||
Use URI encoding as described in RFC 1738.
|
||||
The form is
|
||||
.Ql %xx
|
||||
where
|
||||
.Em x
|
||||
represents a lower case hexadecimal digit.
|
||||
.It Dv VIS_MIMESTYLE
|
||||
Use MIME Quoted-Printable encoding as described in RFC 2045, only don't
|
||||
break lines and don't handle CRLF.
|
||||
The form is:
|
||||
.Ql %XX
|
||||
where
|
||||
.Em X
|
||||
represents an upper case hexadecimal digit.
|
||||
.El
|
||||
.Pp
|
||||
There is one additional flag,
|
||||
.Dv VIS_NOSLASH ,
|
||||
which inhibits the
|
||||
doubling of backslashes and the backslash before the default
|
||||
format (that is, control characters are represented by
|
||||
.Ql ^C
|
||||
and
|
||||
meta characters as
|
||||
.Ql M-C ) .
|
||||
With this flag set, the encoding is
|
||||
ambiguous and non-invertible.
|
||||
.Sh ERRORS
|
||||
The functions
|
||||
.Fn nvis
|
||||
and
|
||||
.Fn snvis
|
||||
will return
|
||||
.Dv NULL
|
||||
and the functions
|
||||
.Fn strnvis ,
|
||||
.Fn strnvisx ,
|
||||
.Fn strsnvis ,
|
||||
and
|
||||
.Fn strsnvisx ,
|
||||
will return \-1 when the
|
||||
.Fa dlen
|
||||
destination buffer length size is not enough to perform the conversion while
|
||||
setting
|
||||
.Va errno
|
||||
to:
|
||||
.Bl -tag -width Er
|
||||
.It Bq Er ENOSPC
|
||||
The destination buffer size is not large enough to perform the conversion.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr unvis 1 ,
|
||||
.Xr vis 1 ,
|
||||
.Xr unvis 3
|
||||
.Rs
|
||||
.%A T. Berners-Lee
|
||||
.%T Uniform Resource Locators (URL)
|
||||
.%O RFC1738
|
||||
.Re
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Fn vis ,
|
||||
.Fn strvis ,
|
||||
and
|
||||
.Fa strvisx
|
||||
functions first appeared in
|
||||
.Bx 4.4 .
|
||||
The
|
||||
.Fn svis ,
|
||||
.Fn strsvis ,
|
||||
and
|
||||
.Fn strsvisx
|
||||
functions appeared in
|
||||
.Nx 1.5 .
|
||||
The buffer size limited versions of the functions
|
||||
.Po Fn nvis ,
|
||||
.Fn strnvis ,
|
||||
.Fn strnvisx ,
|
||||
.Fn snvis ,
|
||||
.Fn strsnvis ,
|
||||
and
|
||||
.Fn strsnvisx Pc
|
||||
appeared in
|
||||
.Nx 6.0 .
|
574
vis.c
Normal file
574
vis.c
Normal file
@ -0,0 +1,574 @@
|
||||
/* $NetBSD: vis.c,v 1.44 2011/03/12 19:52:48 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1999, 2005 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
__RCSID("$NetBSD: vis.c,v 1.44 2011/03/12 19:52:48 christos Exp $");
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include "namespace.h"
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <vis.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __weak_alias
|
||||
__weak_alias(strvisx,_strvisx)
|
||||
#endif
|
||||
|
||||
#if !HAVE_VIS || !HAVE_SVIS
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
static char *do_svis(char *, size_t *, int, int, int, const char *);
|
||||
|
||||
#undef BELL
|
||||
#define BELL '\a'
|
||||
|
||||
#define isoctal(c) (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7')
|
||||
#define iswhite(c) (c == ' ' || c == '\t' || c == '\n')
|
||||
#define issafe(c) (c == '\b' || c == BELL || c == '\r')
|
||||
#define xtoa(c) "0123456789abcdef"[c]
|
||||
#define XTOA(c) "0123456789ABCDEF"[c]
|
||||
|
||||
#define MAXEXTRAS 5
|
||||
|
||||
#define MAKEEXTRALIST(flag, extra, orig_str) \
|
||||
do { \
|
||||
const char *orig = orig_str; \
|
||||
const char *o = orig; \
|
||||
char *e; \
|
||||
while (*o++) \
|
||||
continue; \
|
||||
extra = malloc((size_t)((o - orig) + MAXEXTRAS)); \
|
||||
if (!extra) break; \
|
||||
for (o = orig, e = extra; (*e++ = *o++) != '\0';) \
|
||||
continue; \
|
||||
e--; \
|
||||
if (flag & VIS_SP) *e++ = ' '; \
|
||||
if (flag & VIS_TAB) *e++ = '\t'; \
|
||||
if (flag & VIS_NL) *e++ = '\n'; \
|
||||
if ((flag & VIS_NOSLASH) == 0) *e++ = '\\'; \
|
||||
*e = '\0'; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
/*
|
||||
* This is do_hvis, for HTTP style (RFC 1808)
|
||||
*/
|
||||
static char *
|
||||
do_hvis(char *dst, size_t *dlen, int c, int flag, int nextc, const char *extra)
|
||||
{
|
||||
|
||||
if ((isascii(c) && isalnum(c))
|
||||
/* safe */
|
||||
|| c == '$' || c == '-' || c == '_' || c == '.' || c == '+'
|
||||
/* extra */
|
||||
|| c == '!' || c == '*' || c == '\'' || c == '(' || c == ')'
|
||||
|| c == ',') {
|
||||
dst = do_svis(dst, dlen, c, flag, nextc, extra);
|
||||
} else {
|
||||
if (dlen) {
|
||||
if (*dlen < 3)
|
||||
return NULL;
|
||||
*dlen -= 3;
|
||||
}
|
||||
*dst++ = '%';
|
||||
*dst++ = xtoa(((unsigned int)c >> 4) & 0xf);
|
||||
*dst++ = xtoa((unsigned int)c & 0xf);
|
||||
}
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is do_mvis, for Quoted-Printable MIME (RFC 2045)
|
||||
* NB: No handling of long lines or CRLF.
|
||||
*/
|
||||
static char *
|
||||
do_mvis(char *dst, size_t *dlen, int c, int flag, int nextc, const char *extra)
|
||||
{
|
||||
if ((c != '\n') &&
|
||||
/* Space at the end of the line */
|
||||
((isspace(c) && (nextc == '\r' || nextc == '\n')) ||
|
||||
/* Out of range */
|
||||
(!isspace(c) && (c < 33 || (c > 60 && c < 62) || c > 126)) ||
|
||||
/* Specific char to be escaped */
|
||||
strchr("#$@[\\]^`{|}~", c) != NULL)) {
|
||||
if (dlen) {
|
||||
if (*dlen < 3)
|
||||
return NULL;
|
||||
*dlen -= 3;
|
||||
}
|
||||
*dst++ = '=';
|
||||
*dst++ = XTOA(((unsigned int)c >> 4) & 0xf);
|
||||
*dst++ = XTOA((unsigned int)c & 0xf);
|
||||
} else {
|
||||
dst = do_svis(dst, dlen, c, flag, nextc, extra);
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is do_vis, the central code of vis.
|
||||
* dst: Pointer to the destination buffer
|
||||
* c: Character to encode
|
||||
* flag: Flag word
|
||||
* nextc: The character following 'c'
|
||||
* extra: Pointer to the list of extra characters to be
|
||||
* backslash-protected.
|
||||
*/
|
||||
static char *
|
||||
do_svis(char *dst, size_t *dlen, int c, int flag, int nextc, const char *extra)
|
||||
{
|
||||
int isextra;
|
||||
size_t odlen = dlen ? *dlen : 0;
|
||||
|
||||
isextra = strchr(extra, c) != NULL;
|
||||
#define HAVE(x) \
|
||||
do { \
|
||||
if (dlen) { \
|
||||
if (*dlen < (x)) \
|
||||
goto out; \
|
||||
*dlen -= (x); \
|
||||
} \
|
||||
} while (/*CONSTCOND*/0)
|
||||
if (!isextra && isascii(c) && (isgraph(c) || iswhite(c) ||
|
||||
((flag & VIS_SAFE) && issafe(c)))) {
|
||||
HAVE(1);
|
||||
*dst++ = c;
|
||||
return dst;
|
||||
}
|
||||
if (flag & VIS_CSTYLE) {
|
||||
HAVE(2);
|
||||
switch (c) {
|
||||
case '\n':
|
||||
*dst++ = '\\'; *dst++ = 'n';
|
||||
return dst;
|
||||
case '\r':
|
||||
*dst++ = '\\'; *dst++ = 'r';
|
||||
return dst;
|
||||
case '\b':
|
||||
*dst++ = '\\'; *dst++ = 'b';
|
||||
return dst;
|
||||
case BELL:
|
||||
*dst++ = '\\'; *dst++ = 'a';
|
||||
return dst;
|
||||
case '\v':
|
||||
*dst++ = '\\'; *dst++ = 'v';
|
||||
return dst;
|
||||
case '\t':
|
||||
*dst++ = '\\'; *dst++ = 't';
|
||||
return dst;
|
||||
case '\f':
|
||||
*dst++ = '\\'; *dst++ = 'f';
|
||||
return dst;
|
||||
case ' ':
|
||||
*dst++ = '\\'; *dst++ = 's';
|
||||
return dst;
|
||||
case '\0':
|
||||
*dst++ = '\\'; *dst++ = '0';
|
||||
if (isoctal(nextc)) {
|
||||
HAVE(2);
|
||||
*dst++ = '0';
|
||||
*dst++ = '0';
|
||||
}
|
||||
return dst;
|
||||
default:
|
||||
if (isgraph(c)) {
|
||||
*dst++ = '\\'; *dst++ = c;
|
||||
return dst;
|
||||
}
|
||||
if (dlen)
|
||||
*dlen = odlen;
|
||||
}
|
||||
}
|
||||
if (isextra || ((c & 0177) == ' ') || (flag & VIS_OCTAL)) {
|
||||
HAVE(4);
|
||||
*dst++ = '\\';
|
||||
*dst++ = (u_char)(((u_int32_t)(u_char)c >> 6) & 03) + '0';
|
||||
*dst++ = (u_char)(((u_int32_t)(u_char)c >> 3) & 07) + '0';
|
||||
*dst++ = (c & 07) + '0';
|
||||
} else {
|
||||
if ((flag & VIS_NOSLASH) == 0) {
|
||||
HAVE(1);
|
||||
*dst++ = '\\';
|
||||
}
|
||||
|
||||
if (c & 0200) {
|
||||
HAVE(1);
|
||||
c &= 0177; *dst++ = 'M';
|
||||
}
|
||||
|
||||
if (iscntrl(c)) {
|
||||
HAVE(2);
|
||||
*dst++ = '^';
|
||||
if (c == 0177)
|
||||
*dst++ = '?';
|
||||
else
|
||||
*dst++ = c + '@';
|
||||
} else {
|
||||
HAVE(2);
|
||||
*dst++ = '-'; *dst++ = c;
|
||||
}
|
||||
}
|
||||
return dst;
|
||||
out:
|
||||
*dlen = odlen;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
typedef char *(*visfun_t)(char *, size_t *, int, int, int, const char *);
|
||||
|
||||
/*
|
||||
* Return the appropriate encoding function depending on the flags given.
|
||||
*/
|
||||
static visfun_t
|
||||
getvisfun(int flag)
|
||||
{
|
||||
if (flag & VIS_HTTPSTYLE)
|
||||
return do_hvis;
|
||||
if (flag & VIS_MIMESTYLE)
|
||||
return do_mvis;
|
||||
return do_svis;
|
||||
}
|
||||
|
||||
/*
|
||||
* isnvis - visually encode characters, also encoding the characters
|
||||
* pointed to by `extra'
|
||||
*/
|
||||
static char *
|
||||
isnvis(char *dst, size_t *dlen, int c, int flag, int nextc, const char *extra)
|
||||
{
|
||||
char *nextra = NULL;
|
||||
visfun_t f;
|
||||
|
||||
_DIAGASSERT(dst != NULL);
|
||||
_DIAGASSERT(extra != NULL);
|
||||
MAKEEXTRALIST(flag, nextra, extra);
|
||||
if (!nextra) {
|
||||
if (dlen && *dlen == 0) {
|
||||
errno = ENOSPC;
|
||||
return NULL;
|
||||
}
|
||||
*dst = '\0'; /* can't create nextra, return "" */
|
||||
return dst;
|
||||
}
|
||||
f = getvisfun(flag);
|
||||
dst = (*f)(dst, dlen, c, flag, nextc, nextra);
|
||||
free(nextra);
|
||||
if (dst == NULL || (dlen && *dlen == 0)) {
|
||||
errno = ENOSPC;
|
||||
return NULL;
|
||||
}
|
||||
*dst = '\0';
|
||||
return dst;
|
||||
}
|
||||
|
||||
char *
|
||||
svis(char *dst, int c, int flag, int nextc, const char *extra)
|
||||
{
|
||||
return isnvis(dst, NULL, c, flag, nextc, extra);
|
||||
}
|
||||
|
||||
char *
|
||||
snvis(char *dst, size_t dlen, int c, int flag, int nextc, const char *extra)
|
||||
{
|
||||
return isnvis(dst, &dlen, c, flag, nextc, extra);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* strsvis, strsvisx - visually encode characters from src into dst
|
||||
*
|
||||
* Extra is a pointer to a \0-terminated list of characters to
|
||||
* be encoded, too. These functions are useful e. g. to
|
||||
* encode strings in such a way so that they are not interpreted
|
||||
* by a shell.
|
||||
*
|
||||
* Dst must be 4 times the size of src to account for possible
|
||||
* expansion. The length of dst, not including the trailing NULL,
|
||||
* is returned.
|
||||
*
|
||||
* Strsvisx encodes exactly len bytes from src into dst.
|
||||
* This is useful for encoding a block of data.
|
||||
*/
|
||||
static int
|
||||
istrsnvis(char *dst, size_t *dlen, const char *csrc, int flag, const char *extra)
|
||||
{
|
||||
int c;
|
||||
char *start;
|
||||
char *nextra = NULL;
|
||||
const unsigned char *src = (const unsigned char *)csrc;
|
||||
visfun_t f;
|
||||
|
||||
_DIAGASSERT(dst != NULL);
|
||||
_DIAGASSERT(src != NULL);
|
||||
_DIAGASSERT(extra != NULL);
|
||||
MAKEEXTRALIST(flag, nextra, extra);
|
||||
if (!nextra) {
|
||||
*dst = '\0'; /* can't create nextra, return "" */
|
||||
return 0;
|
||||
}
|
||||
f = getvisfun(flag);
|
||||
for (start = dst; (c = *src++) != '\0'; /* empty */) {
|
||||
dst = (*f)(dst, dlen, c, flag, *src, nextra);
|
||||
if (dst == NULL) {
|
||||
errno = ENOSPC;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
free(nextra);
|
||||
if (dlen && *dlen == 0) {
|
||||
errno = ENOSPC;
|
||||
return -1;
|
||||
}
|
||||
*dst = '\0';
|
||||
return (int)(dst - start);
|
||||
}
|
||||
|
||||
int
|
||||
strsvis(char *dst, const char *csrc, int flag, const char *extra)
|
||||
{
|
||||
return istrsnvis(dst, NULL, csrc, flag, extra);
|
||||
}
|
||||
|
||||
int
|
||||
strsnvis(char *dst, size_t dlen, const char *csrc, int flag, const char *extra)
|
||||
{
|
||||
return istrsnvis(dst, &dlen, csrc, flag, extra);
|
||||
}
|
||||
|
||||
static int
|
||||
istrsnvisx(char *dst, size_t *dlen, const char *csrc, size_t len, int flag,
|
||||
const char *extra)
|
||||
{
|
||||
unsigned char c;
|
||||
char *start;
|
||||
char *nextra = NULL;
|
||||
const unsigned char *src = (const unsigned char *)csrc;
|
||||
visfun_t f;
|
||||
|
||||
_DIAGASSERT(dst != NULL);
|
||||
_DIAGASSERT(src != NULL);
|
||||
_DIAGASSERT(extra != NULL);
|
||||
MAKEEXTRALIST(flag, nextra, extra);
|
||||
if (! nextra) {
|
||||
if (dlen && *dlen == 0) {
|
||||
errno = ENOSPC;
|
||||
return -1;
|
||||
}
|
||||
*dst = '\0'; /* can't create nextra, return "" */
|
||||
return 0;
|
||||
}
|
||||
|
||||
f = getvisfun(flag);
|
||||
for (start = dst; len > 0; len--) {
|
||||
c = *src++;
|
||||
dst = (*f)(dst, dlen, c, flag, len > 1 ? *src : '\0', nextra);
|
||||
if (dst == NULL) {
|
||||
errno = ENOSPC;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
free(nextra);
|
||||
if (dlen && *dlen == 0) {
|
||||
errno = ENOSPC;
|
||||
return -1;
|
||||
}
|
||||
*dst = '\0';
|
||||
return (int)(dst - start);
|
||||
}
|
||||
|
||||
int
|
||||
strsvisx(char *dst, const char *csrc, size_t len, int flag, const char *extra)
|
||||
{
|
||||
return istrsnvisx(dst, NULL, csrc, len, flag, extra);
|
||||
}
|
||||
|
||||
int
|
||||
strsnvisx(char *dst, size_t dlen, const char *csrc, size_t len, int flag,
|
||||
const char *extra)
|
||||
{
|
||||
return istrsnvisx(dst, &dlen, csrc, len, flag, extra);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !HAVE_VIS
|
||||
/*
|
||||
* vis - visually encode characters
|
||||
*/
|
||||
static char *
|
||||
invis(char *dst, size_t *dlen, int c, int flag, int nextc)
|
||||
{
|
||||
char *extra = NULL;
|
||||
unsigned char uc = (unsigned char)c;
|
||||
visfun_t f;
|
||||
|
||||
_DIAGASSERT(dst != NULL);
|
||||
|
||||
MAKEEXTRALIST(flag, extra, "");
|
||||
if (! extra) {
|
||||
if (dlen && *dlen == 0) {
|
||||
errno = ENOSPC;
|
||||
return NULL;
|
||||
}
|
||||
*dst = '\0'; /* can't create extra, return "" */
|
||||
return dst;
|
||||
}
|
||||
f = getvisfun(flag);
|
||||
dst = (*f)(dst, dlen, uc, flag, nextc, extra);
|
||||
free(extra);
|
||||
if (dst == NULL || (dlen && *dlen == 0)) {
|
||||
errno = ENOSPC;
|
||||
return NULL;
|
||||
}
|
||||
*dst = '\0';
|
||||
return dst;
|
||||
}
|
||||
|
||||
char *
|
||||
vis(char *dst, int c, int flag, int nextc)
|
||||
{
|
||||
return invis(dst, NULL, c, flag, nextc);
|
||||
}
|
||||
|
||||
char *
|
||||
nvis(char *dst, size_t dlen, int c, int flag, int nextc)
|
||||
{
|
||||
return invis(dst, &dlen, c, flag, nextc);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* strvis, strvisx - visually encode characters from src into dst
|
||||
*
|
||||
* Dst must be 4 times the size of src to account for possible
|
||||
* expansion. The length of dst, not including the trailing NULL,
|
||||
* is returned.
|
||||
*
|
||||
* Strvisx encodes exactly len bytes from src into dst.
|
||||
* This is useful for encoding a block of data.
|
||||
*/
|
||||
static int
|
||||
istrnvis(char *dst, size_t *dlen, const char *src, int flag)
|
||||
{
|
||||
char *extra = NULL;
|
||||
int rv;
|
||||
|
||||
MAKEEXTRALIST(flag, extra, "");
|
||||
if (!extra) {
|
||||
if (dlen && *dlen == 0) {
|
||||
errno = ENOSPC;
|
||||
return -1;
|
||||
}
|
||||
*dst = '\0'; /* can't create extra, return "" */
|
||||
return 0;
|
||||
}
|
||||
rv = istrsnvis(dst, dlen, src, flag, extra);
|
||||
free(extra);
|
||||
return rv;
|
||||
}
|
||||
|
||||
int
|
||||
strvis(char *dst, const char *src, int flag)
|
||||
{
|
||||
return istrnvis(dst, NULL, src, flag);
|
||||
}
|
||||
|
||||
int
|
||||
strnvis(char *dst, size_t dlen, const char *src, int flag)
|
||||
{
|
||||
return istrnvis(dst, &dlen, src, flag);
|
||||
}
|
||||
|
||||
static int
|
||||
istrnvisx(char *dst, size_t *dlen, const char *src, size_t len, int flag)
|
||||
{
|
||||
char *extra = NULL;
|
||||
int rv;
|
||||
|
||||
MAKEEXTRALIST(flag, extra, "");
|
||||
if (!extra) {
|
||||
if (dlen && *dlen == 0) {
|
||||
errno = ENOSPC;
|
||||
return -1;
|
||||
}
|
||||
*dst = '\0'; /* can't create extra, return "" */
|
||||
return 0;
|
||||
}
|
||||
rv = istrsnvisx(dst, dlen, src, len, flag, extra);
|
||||
free(extra);
|
||||
return rv;
|
||||
}
|
||||
|
||||
int
|
||||
strvisx(char *dst, const char *src, size_t len, int flag)
|
||||
{
|
||||
return istrnvisx(dst, NULL, src, len, flag);
|
||||
}
|
||||
|
||||
int
|
||||
strnvisx(char *dst, size_t dlen, const char *src, size_t len, int flag)
|
||||
{
|
||||
return istrnvisx(dst, &dlen, src, len, flag);
|
||||
}
|
||||
|
||||
#endif
|
112
vis.h
Normal file
112
vis.h
Normal file
@ -0,0 +1,112 @@
|
||||
/* $NetBSD: vis.h,v 1.19 2011/03/12 19:52:45 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)vis.h 8.1 (Berkeley) 6/2/93
|
||||
*/
|
||||
|
||||
#ifndef _VIS_H_
|
||||
#define _VIS_H_
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
/*
|
||||
* to select alternate encoding format
|
||||
*/
|
||||
#define VIS_OCTAL 0x001 /* use octal \ddd format */
|
||||
#define VIS_CSTYLE 0x002 /* use \[nrft0..] where appropiate */
|
||||
|
||||
/*
|
||||
* to alter set of characters encoded (default is to encode all
|
||||
* non-graphic except space, tab, and newline).
|
||||
*/
|
||||
#define VIS_SP 0x004 /* also encode space */
|
||||
#define VIS_TAB 0x008 /* also encode tab */
|
||||
#define VIS_NL 0x010 /* also encode newline */
|
||||
#define VIS_WHITE (VIS_SP | VIS_TAB | VIS_NL)
|
||||
#define VIS_SAFE 0x020 /* only encode "unsafe" characters */
|
||||
|
||||
/*
|
||||
* other
|
||||
*/
|
||||
#define VIS_NOSLASH 0x040 /* inhibit printing '\' */
|
||||
#define VIS_HTTP1808 0x080 /* http-style escape % hex hex */
|
||||
#define VIS_HTTPSTYLE 0x080 /* http-style escape % hex hex */
|
||||
#define VIS_MIMESTYLE 0x100 /* mime-style escape = HEX HEX */
|
||||
#define VIS_HTTP1866 0x200 /* http-style &#num; or &string; */
|
||||
#define VIS_NOESCAPE 0x400 /* don't decode `\' */
|
||||
#define _VIS_END 0x800 /* for unvis */
|
||||
|
||||
/*
|
||||
* unvis return codes
|
||||
*/
|
||||
#define UNVIS_VALID 1 /* character valid */
|
||||
#define UNVIS_VALIDPUSH 2 /* character valid, push back passed char */
|
||||
#define UNVIS_NOCHAR 3 /* valid sequence, no character produced */
|
||||
#define UNVIS_SYNBAD -1 /* unrecognized escape sequence */
|
||||
#define UNVIS_ERROR -2 /* decoder in unknown state (unrecoverable) */
|
||||
|
||||
/*
|
||||
* unvis flags
|
||||
*/
|
||||
#define UNVIS_END _VIS_END /* no more characters */
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
char *vis(char *, int, int, int);
|
||||
char *nvis(char *, size_t, int, int, int);
|
||||
|
||||
char *svis(char *, int, int, int, const char *);
|
||||
char *snvis(char *, size_t, int, int, int, const char *);
|
||||
|
||||
int strvis(char *, const char *, int);
|
||||
int strnvis(char *, size_t, const char *, int);
|
||||
|
||||
int strsvis(char *, const char *, int, const char *);
|
||||
int strsnvis(char *, size_t, const char *, int, const char *);
|
||||
|
||||
int strvisx(char *, const char *, size_t, int);
|
||||
int strnvisx(char *, size_t, const char *, size_t, int);
|
||||
|
||||
int strsvisx(char *, const char *, size_t, int, const char *);
|
||||
int strsnvisx(char *, size_t, const char *, size_t, int, const char *);
|
||||
|
||||
int strunvis(char *, const char *);
|
||||
int strnunvis(char *, size_t, const char *);
|
||||
|
||||
int strunvisx(char *, const char *, int);
|
||||
int strnunvisx(char *, size_t, const char *, int);
|
||||
|
||||
#ifndef __LIBC12_SOURCE__
|
||||
int unvis(char *, int, int *, int) __RENAME(__unvis50);
|
||||
#endif
|
||||
__END_DECLS
|
||||
|
||||
#endif /* !_VIS_H_ */
|
Loading…
x
Reference in New Issue
Block a user