xref: /onnv-gate/usr/src/cmd/ast/msgcc/msgcvt.c (revision 10898:1883b621b3ea)
14887Schin /***********************************************************************
24887Schin *                                                                      *
34887Schin *               This software is part of the ast package               *
4*10898Sroland.mainz@nrubsig.org *          Copyright (c) 2000-2009 AT&T Intellectual Property          *
54887Schin *                      and is licensed under the                       *
64887Schin *                  Common Public License, Version 1.0                  *
78462SApril.Chin@Sun.COM *                    by AT&T Intellectual Property                     *
84887Schin *                                                                      *
94887Schin *                A copy of the License is available at                 *
104887Schin *            http://www.opensource.org/licenses/cpl1.0.txt             *
114887Schin *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
124887Schin *                                                                      *
134887Schin *              Information and Software Systems Research               *
144887Schin *                            AT&T Research                             *
154887Schin *                           Florham Park NJ                            *
164887Schin *                                                                      *
174887Schin *                 Glenn Fowler <gsf@research.att.com>                  *
184887Schin *                                                                      *
194887Schin ***********************************************************************/
204887Schin #pragma prototyped
214887Schin /*
224887Schin  * Glenn Fowler
234887Schin  * AT&T Research
244887Schin  */
254887Schin 
264887Schin static const char usage[] =
274887Schin "[-?\n@(#)$Id: msgcvt (AT&T Research) 2000-05-01 $\n]"
284887Schin USAGE_LICENSE
294887Schin "[+NAME?msgcvt - convert message file to/from html]"
304887Schin "[+DESCRIPTION?\bmsgcvt\b reads a \bgencat\b(1) format file on the standard"
314887Schin "	input and converts it to \bhtml\b on the standard output. The input"
324887Schin "	file must contain the control statement \b$quote \"\b and use the \""
334887Schin "	character to quote message text. The output is in a form suitable for"
344887Schin "	automatic translation by web sites like"
354887Schin "	\bhttp://babelfish.altavista.com/\b or filters like"
364887Schin "	\btranslate\b(1).]"
374887Schin "[h:html?Generate \bhtml\b from \bgencat\b(1) input. This is the default.]"
384887Schin "[m:msg?Generate a \bgencat\b(1) message file from (presumably translated)"
394887Schin "	\bhtml\b. Wide characters are UTF-8 encoded.]"
404887Schin "[r:raw?The message file is raw message text, one message per line, with no"
414887Schin "	quoting or line numbering.]"
424887Schin "[+SEE ALSO?\bgencat\b(1), \bmsgcc\b(1), \bmsggen\b(1), \btranslate\b(1)]"
434887Schin ;
444887Schin 
454887Schin #include <ast.h>
464887Schin #include <ctype.h>
474887Schin #include <error.h>
484887Schin 
494887Schin #define MSG_RAW		(1<<0)
504887Schin #define MSG_SPLICE	(1<<1)
514887Schin 
524887Schin #define SPACE(s)	(isspace(*s)&&(s+=1)||*s=='\\'&&(*(s+1)=='n'||*(s+1)=='t')&&(s+=2))
534887Schin 
544887Schin typedef void (*Convert_f)(Sfio_t*, Sfio_t*, int);
554887Schin 
564887Schin typedef struct
574887Schin {
584887Schin 	const char*	name;
594887Schin 	int		code;
604887Schin } Code_t;
614887Schin 
624887Schin static const Code_t	codes[] =
634887Schin {
644887Schin 	"aacute",	225,
654887Schin 	"Aacute",	193,
664887Schin 	"acirc",	226,
674887Schin 	"Acirc",	194,
684887Schin 	"aelig",	230,
694887Schin 	"AElig",	198,
704887Schin 	"agrave",	224,
714887Schin 	"Agrave",	192,
724887Schin 	"amp",		'&',
734887Schin 	"aring",	229,
744887Schin 	"Aring",	197,
754887Schin 	"atilde",	227,
764887Schin 	"Atilde",	195,
774887Schin 	"auml",		228,
784887Schin 	"Auml",		196,
794887Schin 	"ccedil",	231,
804887Schin 	"Ccedil",	199,
814887Schin 	"copy",		169,
824887Schin 	"eacute",	233,
834887Schin 	"Eacute",	201,
844887Schin 	"ecirc",	234,
854887Schin 	"Ecirc",	202,
864887Schin 	"egrave",	232,
874887Schin 	"Egrave",	200,
884887Schin 	"euml",		235,
894887Schin 	"Euml",		203,
904887Schin 	"gt",		'>',
914887Schin 	"iacute",	237,
924887Schin 	"Iacute",	205,
934887Schin 	"icirc",	238,
944887Schin 	"Icirc",	206,
954887Schin 	"igrave",	236,
964887Schin 	"Igrave",	204,
974887Schin 	"iuml",		239,
984887Schin 	"Iuml",		207,
994887Schin 	"lt",		'<',
1004887Schin 	"nbsp",		' ',
1014887Schin 	"ntilde",	241,
1024887Schin 	"Ntilde",	209,
1034887Schin 	"oacute",	243,
1044887Schin 	"Oacute",	211,
1054887Schin 	"ocirc",	244,
1064887Schin 	"Ocirc",	212,
1074887Schin 	"ograve",	242,
1084887Schin 	"Ograve",	210,
1094887Schin 	"oslash",	248,
1104887Schin 	"Oslash",	216,
1114887Schin 	"otilde",	245,
1124887Schin 	"Otilde",	213,
1134887Schin 	"ouml",		246,
1144887Schin 	"Ouml",		214,
1154887Schin 	"quot",		'"',
1164887Schin 	"reg",		174,
1174887Schin 	"szlig",	223,
1184887Schin 	"uacute",	250,
1194887Schin 	"Uacute",	218,
1204887Schin 	"ucirc",	251,
1214887Schin 	"Ucirc",	219,
1224887Schin 	"ugrave",	249,
1234887Schin 	"Ugrave",	217,
1244887Schin 	"uuml",		252,
1254887Schin 	"Uuml",		220,
1264887Schin 	"yuml",		255,
1274887Schin };
1284887Schin 
1294887Schin static int
decode(Sfio_t * ip)1304887Schin decode(Sfio_t* ip)
1314887Schin {
1324887Schin 	register int	c;
1334887Schin 	register int	i;
1344887Schin 	char		name[32];
1354887Schin 
1364887Schin 	if ((c = sfgetc(ip)) == EOF)
1374887Schin 		return '&';
1384887Schin 	name[0] = c;
1394887Schin 	i = 1;
1404887Schin 	if (c != '#' && !isalpha(c))
1414887Schin 		goto bad;
1424887Schin 	while ((c = sfgetc(ip)) != EOF && c != ';')
1434887Schin 	{
1444887Schin 		if (c == '&')
1454887Schin 			i = 0;
1464887Schin 		else
1474887Schin 		{
1484887Schin 			name[i++] = c;
1494887Schin 			if (!isalnum(c) && (i > 1 || c != '#') || i >= (elementsof(name) - 1))
1504887Schin 				goto bad;
1514887Schin 		}
1524887Schin 	}
1534887Schin 	name[i] = 0;
1544887Schin 	if (name[0] == '#')
1554887Schin 	{
1564887Schin 		switch (c = strtol(name + 1, NiL, 10))
1574887Schin 		{
1584887Schin 		case 91:
1594887Schin 			c = '[';
1604887Schin 			break;
1614887Schin 		case 93:
1624887Schin 			c = ']';
1634887Schin 			break;
1644887Schin 		}
1654887Schin 	}
1664887Schin 	else
1674887Schin 	{
1684887Schin 		for (i = 0; i < elementsof(codes); i++)
1694887Schin 			if (streq(codes[i].name, name))
1704887Schin 			{
1714887Schin 				c = codes[i].code;
1724887Schin 				break;
1734887Schin 			}
1744887Schin 		if (i >= elementsof(codes))
1754887Schin 			goto bad;
1764887Schin 	}
1774887Schin 	return c;
1784887Schin  bad:
1794887Schin 	name[i] = 0;
1804887Schin 	if (c == ';')
1814887Schin 		error(1, "&%s: unknown HTML special character -- & assumed", name);
1824887Schin 	else
1834887Schin 		error(1, "&%s: invalid HTML special character -- & assumed", name);
1844887Schin 	while (i--)
1854887Schin 		sfungetc(ip, name[i]);
1864887Schin 	return '&';
1874887Schin }
1884887Schin 
1894887Schin static int
sfpututf(Sfio_t * op,register int w)1904887Schin sfpututf(Sfio_t* op, register int w)
1914887Schin {
1924887Schin 	if (!(w & ~0x7F))
1934887Schin 		return sfputc(op, w);
1944887Schin 	else if (!(w & ~0x7FF))
1954887Schin 		sfputc(op, 0xC0 + (w >> 6));
1964887Schin 	else if (!(w & ~0xFFFF))
1974887Schin 	{
1984887Schin 		sfputc(op, 0xE0 + (w >> 12));
1994887Schin 		sfputc(op, 0x80 + (w >> 6 ) & 0x3F);
2004887Schin 	}
2014887Schin 	else
2024887Schin 		return sfputc(op, '?');
2034887Schin 	return sfputc(op, 0x80 + (w & 0x3F));
2044887Schin }
2054887Schin 
2064887Schin static int
sfnext(Sfio_t * ip)2074887Schin sfnext(Sfio_t* ip)
2084887Schin {
2094887Schin 	register int	c;
2104887Schin 
2114887Schin 	while (isspace(c = sfgetc(ip)));
2124887Schin 	return c;
2134887Schin }
2144887Schin 
2154887Schin static void
html2msg(register Sfio_t * ip,register Sfio_t * op,int flags)2164887Schin html2msg(register Sfio_t* ip, register Sfio_t* op, int flags)
2174887Schin {
2184887Schin 	register int	c;
2194887Schin 	register int	q;
2204887Schin 
2214887Schin  again:
2224887Schin 	while ((c = sfgetc(ip)) != EOF)
2234887Schin 		if (c == '<')
2244887Schin 		{
2254887Schin 			if ((c = sfnext(ip)) == 'O' &&
2264887Schin 			    (c = sfnext(ip)) == 'L' &&
2274887Schin 			    isspace(c = sfgetc(ip)) &&
2284887Schin 			    (c = sfnext(ip)) == 'S' &&
2294887Schin 			    (c = sfnext(ip)) == 'T' &&
2304887Schin 			    (c = sfnext(ip)) == 'A' &&
2314887Schin 			    (c = sfnext(ip)) == 'R' &&
2324887Schin 			    (c = sfnext(ip)) == 'T' &&
2334887Schin 			    (c = sfnext(ip)) == '=' &&
2344887Schin 			    (c = sfnext(ip)) == '"' &&
2354887Schin 			    (c = sfnext(ip)) == '5' &&
2364887Schin 			    (c = sfnext(ip)) == '5' &&
2374887Schin 			    (c = sfnext(ip)) == '0' &&
2384887Schin 			    (c = sfnext(ip)) == '7' &&
2394887Schin 			    (c = sfnext(ip)) == '1' &&
2404887Schin 			    (c = sfnext(ip)) == '7' &&
2414887Schin 			    (c = sfnext(ip)) == '"' &&
2424887Schin 			    (c = sfnext(ip)) == '>')
2434887Schin 				break;
2444887Schin 			while (c != EOF && c != '>')
2454887Schin 				c = sfgetc(ip);
2464887Schin 		}
2474887Schin 	if ((c = sfnext(ip)) != EOF)
2484887Schin 		sfungetc(ip, c);
2494887Schin 	q = 0;
2504887Schin 	for (;;)
2514887Schin 	{
2524887Schin 		switch (c = sfgetc(ip))
2534887Schin 		{
2544887Schin 		case EOF:
2554887Schin 			break;
2564887Schin 		case '&':
2574887Schin 			c = decode(ip);
2584887Schin 			sfpututf(op, c);
2594887Schin 			if (isspace(c))
2604887Schin 			{
2614887Schin 				while (isspace(c = sfgetc(ip)));
2624887Schin 				if (c == EOF)
2634887Schin 					break;
2644887Schin 				sfungetc(ip, c);
2654887Schin 			}
2664887Schin 			continue;
2674887Schin 		case '<':
2684887Schin 			switch (c = sfnext(ip))
2694887Schin 			{
2704887Schin 			case '/':
2714887Schin 				if ((c = sfnext(ip)) == 'O' &&
2724887Schin 				    (c = sfgetc(ip)) == 'L' &&
2734887Schin 				    (c = sfnext(ip)) == '>')
2744887Schin 				{
2754887Schin 					if (q)
2764887Schin 					{
2774887Schin 						sfputc(op, q);
2784887Schin 						q = '"';
2794887Schin 					}
2804887Schin 					goto again;
2814887Schin 				}
2824887Schin 				break;
2834887Schin 			case 'B':
2844887Schin 				if ((c = sfgetc(ip)) == 'R' &&
2854887Schin 				    (c = sfnext(ip)) == '>')
2864887Schin 					sfputc(op, ' ');
2874887Schin 				break;
2884887Schin 			case 'L':
2894887Schin 				if ((c = sfgetc(ip)) == 'I' &&
2904887Schin 				    (c = sfnext(ip)) == '>' &&
2914887Schin 				     isdigit(c = sfnext(ip)))
2924887Schin 				{
2934887Schin 					if (q)
2944887Schin 						sfputc(op, q);
2954887Schin 					else
2964887Schin 						q = '"';
2974887Schin 					sfputc(op, '\n');
2984887Schin 					do
2994887Schin 					{
3004887Schin 						sfputc(op, c);
3014887Schin 					} while (isdigit(c = sfgetc(ip)));
3024887Schin 					if (c == EOF)
3034887Schin 						break;
3044887Schin 					sfputc(op, ' ');
3054887Schin 					sfputc(op, '"');
3064887Schin 					if (isspace(c))
3074887Schin 						c = sfnext(ip);
3084887Schin 					if (c == '<' &&
3094887Schin 					    (c = sfnext(ip)) == 'L' &&
3104887Schin 					    (c = sfgetc(ip)) == 'I' &&
3114887Schin 					    (c = sfnext(ip)) == '>')
3124887Schin 						/* great */;
3134887Schin 					continue;
3144887Schin 				}
3154887Schin 				break;
3164887Schin 			case 'P':
3174887Schin 				if ((c = sfnext(ip)) == '>')
3184887Schin 					sfputc(op, '\n');
3194887Schin 				else if (c == 'C' &&
3204887Schin 					 (c = sfgetc(ip)) == 'L' &&
3214887Schin 					 (c = sfgetc(ip)) == 'A' &&
3224887Schin 					 (c = sfgetc(ip)) == 'S' &&
3234887Schin 					 (c = sfgetc(ip)) == 'S' &&
3244887Schin 					 (c = sfnext(ip)) == '=' &&
3254887Schin 					 (c = sfnext(ip)) == '"')
3264887Schin 					for (;;)
3274887Schin 					{
3284887Schin 						switch (c = sfgetc(ip))
3294887Schin 						{
3304887Schin 						case EOF:
3314887Schin 						case '"':
3324887Schin 							break;
3334887Schin 						case '&':
3344887Schin 							c = decode(ip);
3354887Schin 							sfpututf(op, c);
3364887Schin 							continue;
3374887Schin 						default:
3384887Schin 							sfpututf(op, c);
3394887Schin 							continue;
3404887Schin 						}
3414887Schin 						break;
3424887Schin 					}
3434887Schin 				break;
3444887Schin 			}
3454887Schin 			while (c != EOF && c != '>')
3464887Schin 				c = sfgetc(ip);
3474887Schin 			if (c == EOF || (c = sfgetc(ip)) == EOF)
3484887Schin 				break;
3494887Schin 			sfungetc(ip, c);
3504887Schin 			continue;
3514887Schin 		case '"':
3524887Schin 			if (!flags)
3534887Schin 				sfputc(op, '\\');
3544887Schin 			sfputc(op, c);
3554887Schin 			continue;
3564887Schin 		case '\n':
3574887Schin 			if (flags)
3584887Schin 			{
3594887Schin 				sfputc(op, c);
3604887Schin 				continue;
3614887Schin 			}
3624887Schin 			/*FALLTHROUGH*/
3634887Schin 		case ' ':
3644887Schin 		case '\t':
3654887Schin 			while ((c = sfgetc(ip)) != EOF)
3664887Schin 				if (c == '&')
3674887Schin 				{
3684887Schin 					c = decode(ip);
3694887Schin 					if (!isspace(c))
3704887Schin 						sfputc(op, ' ');
3714887Schin 					sfpututf(op, c);
3724887Schin 					break;
3734887Schin 				}
3744887Schin 				else if (!isspace(c))
3754887Schin 				{
3764887Schin 					if (c == '<')
3774887Schin 					{
3784887Schin 						c = sfgetc(ip);
3794887Schin 						if (c == EOF)
3804887Schin 							break;
3814887Schin 						sfungetc(ip, c);
3824887Schin 						sfungetc(ip, '<');
3834887Schin 						if (c != 'L' && c != '/')
3844887Schin 							sfputc(op, ' ');
3854887Schin 					}
3864887Schin 					else
3874887Schin 					{
3884887Schin 						if (c != EOF)
3894887Schin 							sfungetc(ip, c);
3904887Schin 						sfputc(op, ' ');
3914887Schin 					}
3924887Schin 					break;
3934887Schin 				}
3944887Schin 			continue;
3954887Schin 		case '\r':
3964887Schin 		case '[':
3974887Schin 		case ']':
3984887Schin 			continue;
3994887Schin 		default:
4004887Schin 			sfpututf(op, c);
4014887Schin 			continue;
4024887Schin 		}
4034887Schin 		break;
4044887Schin 	}
4054887Schin 	if (q)
4064887Schin 		sfputc(op, q);
4074887Schin 	sfputc(op, '\n');
4084887Schin }
4094887Schin 
4104887Schin static void
encode(Sfio_t * op,register int c)4114887Schin encode(Sfio_t* op, register int c)
4124887Schin {
4134887Schin 	if (c == '<')
4144887Schin 		sfprintf(op, "&lt;");
4154887Schin 	else if (c == '>')
4164887Schin 		sfprintf(op, "&gt;");
4174887Schin 	else if (c == '"')
4184887Schin 		sfprintf(op, "&quot;");
4194887Schin 	else if (c == '&')
4204887Schin 		sfprintf(op, "&amp;");
4214887Schin 	else if (c == '[')
4224887Schin 		sfprintf(op, "&#091;");
4234887Schin 	else if (c == ']')
4244887Schin 		sfprintf(op, "&#093;");
4254887Schin 	else
4264887Schin 		sfputc(op, c);
4274887Schin }
4284887Schin 
4294887Schin static void
msg2html(register Sfio_t * ip,register Sfio_t * op,register int flags)4304887Schin msg2html(register Sfio_t* ip, register Sfio_t* op, register int flags)
4314887Schin {
4324887Schin 	register char*	s;
4334887Schin 	register int	c;
4344887Schin 	register int	q;
4354887Schin 	register int	p;
4364887Schin 
4374887Schin 	sfprintf(op, "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\"><HTML><HEAD><!-- text massaged for external translation --></HEAD><BODY>\n");
4384887Schin 	sfprintf(op, "<OL START=\"550717\">\n");
4394887Schin 	p = q = 0;
4404887Schin 	while (s = sfgetr(ip, '\n', 1))
4414887Schin 	{
4424887Schin 		error_info.line++;
4434887Schin 		if (flags)
4444887Schin 			sfprintf(op, "<P>");
4454887Schin 		else
4464887Schin 		{
4474887Schin 			if (*s == '$')
4484887Schin 			{
4494887Schin 				if (p)
4504887Schin 					sfprintf(op, "<P>");
4514887Schin 				else
4524887Schin 					p = 1;
4534887Schin 				sfprintf(op, "<P CLASS=\"", s);
4544887Schin 				while (c = *s++)
4554887Schin 					encode(op, c);
4564887Schin 				sfprintf(op, "\">\n");
4574887Schin 				continue;
4584887Schin 			}
4594887Schin 			p = 0;
4604887Schin 			if (!isdigit(*s))
4614887Schin 				continue;
4624887Schin 			sfprintf(op, "<LI>");
4634887Schin 			while (isdigit(c = *s++))
4644887Schin 				sfputc(op, c);
4654887Schin 			sfprintf(op, "<LI>");
4664887Schin 			while (c && c != '"')
4674887Schin 				c = *s++;
4684887Schin 			if (!c)
4694887Schin 				s--;
4704887Schin 			else if (isspace(*s))
4714887Schin 			{
4724887Schin 				s++;
4734887Schin 				sfprintf(op, "<BR>");
4744887Schin 			}
4754887Schin 		}
4764887Schin 		for (;;)
4774887Schin 		{
4784887Schin 			switch (c = *s++)
4794887Schin 			{
4804887Schin 			case 0:
4814887Schin 				flags &= ~MSG_SPLICE;
4824887Schin 				if (q)
4834887Schin 				{
4844887Schin 					q = 0;
4854887Schin 					sfprintf(op, "\">");
4864887Schin 				}
4874887Schin 				sfputc(op, '\n');
4884887Schin 				break;
4894887Schin 			case '<':
4904887Schin 				sfprintf(op, "&lt;");
4914887Schin 				continue;
4924887Schin 			case '>':
4934887Schin 				sfprintf(op, "&gt;");
4944887Schin 				continue;
4954887Schin 			case '&':
4964887Schin 				sfprintf(op, "&amp;");
4974887Schin 				continue;
4984887Schin 			case '[':
4994887Schin 				sfprintf(op, "&#091;");
5004887Schin 				continue;
5014887Schin 			case ']':
5024887Schin 				sfprintf(op, "&#093;");
5034887Schin 				continue;
5044887Schin 			case '$':
5054887Schin 				if (!q)
5064887Schin 				{
5074887Schin 					q = 1;
5084887Schin 					sfprintf(op, "<P CLASS=\"");
5094887Schin 				}
5104887Schin 				sfputc(op, c);
5114887Schin 				while (isalnum(c = *s++))
5124887Schin 					sfputc(op, c);
5134887Schin 				s--;
5144887Schin 				continue;
5154887Schin 			case '%':
5164887Schin 				if (!q)
5174887Schin 				{
5184887Schin 					q = 1;
5194887Schin 					sfprintf(op, "<P CLASS=\"");
5204887Schin 				}
5214887Schin 				sfputc(op, c);
5224887Schin 				if (*s == '%')
5234887Schin 					sfputc(op, *s++);
5244887Schin 				else
5254887Schin 					do
5264887Schin 					{
5274887Schin 						if (!(c = *s++) || c == '"')
5284887Schin 						{
5294887Schin 							s--;
5304887Schin 							break;
5314887Schin 						}
5324887Schin 						encode(op, c);
5334887Schin 					} while (!isalpha(c) || (!islower(c) || c == 'h' || c == 'l') && isalpha(*s));
5344887Schin 				if (SPACE(s))
5354887Schin 					sfprintf(op, "&nbsp;");
5364887Schin 				continue;
5374887Schin 			case '"':
5384887Schin 				if (!(flags & MSG_RAW))
5394887Schin 				{
5404887Schin 					s = "";
5414887Schin 					continue;
5424887Schin 				}
5434887Schin 				/*FALLTHROUGH*/
5444887Schin 			case '\'':
5454887Schin 			case ':':
5464887Schin 			case '/':
5474887Schin 			case '+':
5484887Schin 			case '@':
5494887Schin 				if (!q)
5504887Schin 				{
5514887Schin 					q = 1;
5524887Schin 					sfprintf(op, "<P CLASS=\"");
5534887Schin 				}
5544887Schin 				/*FALLTHROUGH*/
5554887Schin 			case '.':
5564887Schin 			case ',':
5574887Schin 				sfputc(op, c);
5584887Schin 				if (SPACE(s))
5594887Schin 					sfprintf(op, "&nbsp;");
5604887Schin 				continue;
5614887Schin 			case '\\':
5624887Schin 				if (!(c = *s++))
5634887Schin 				{
5644887Schin 					flags |= MSG_SPLICE;
5654887Schin 					break;
5664887Schin 				}
5674887Schin 				if (c != 'n' && c != 't')
5684887Schin 				{
5694887Schin 					if (!q)
5704887Schin 					{
5714887Schin 						q = 1;
5724887Schin 						sfprintf(op, "<P CLASS=\"");
5734887Schin 					}
5744887Schin 					sfputc(op, '\\');
5754887Schin 					encode(op, c);
5764887Schin 					if (c == 'b')
5774887Schin 					{
5784887Schin 						for (;;)
5794887Schin 						{
5804887Schin 							if (!(c = *s++) || c == '"')
5814887Schin 							{
5824887Schin 								s--;
5834887Schin 								break;
5844887Schin 							}
5854887Schin 							if (c == '?')
5864887Schin 							{
5874887Schin 								if (*s != '?')
5884887Schin 								{
5894887Schin 									s--;
5904887Schin 									break;
5914887Schin 								}
5924887Schin 								sfputc(op, c);
5934887Schin 								sfputc(op, *s++);
5944887Schin 								continue;
5954887Schin 							}
5964887Schin 							if (c == '\\')
5974887Schin 							{
5984887Schin 								if (!*s)
5994887Schin 									break;
6004887Schin 								sfputc(op, c);
6014887Schin 								if (*s == 'a' || *s == 'b' || *s == '0')
6024887Schin 								{
6034887Schin 									sfputc(op, *s++);
6044887Schin 									break;
6054887Schin 								}
6064887Schin 								c = *s++;
6074887Schin 							}
6084887Schin 							encode(op, c);
6094887Schin 						}
6104887Schin 					}
6114887Schin 					else if (isdigit(c) && isdigit(*s))
6124887Schin 					{
6134887Schin 						sfputc(op, *s++);
6144887Schin 						if (isdigit(*s))
6154887Schin 							sfputc(op, *s++);
6164887Schin 					}
6174887Schin 					if (SPACE(s))
6184887Schin 						sfprintf(op, "&nbsp;");
6194887Schin 					continue;
6204887Schin 				}
6214887Schin 				/*FALLTHROUGH*/
6224887Schin 			case ' ':
6234887Schin 			case '\t':
6244887Schin 				while (isspace(*s) || *s == '\\' && (*(s + 1) == 'n' || *(s + 1) == 't') && s++)
6254887Schin 					s++;
6264887Schin 				if (*s == '"')
6274887Schin 				{
6284887Schin 					if (q)
6294887Schin 					{
6304887Schin 						q = 0;
6314887Schin 						sfprintf(op, " \">");
6324887Schin 					}
6334887Schin 					else
6344887Schin 						sfprintf(op, "<BR>");
6354887Schin 					continue;
6364887Schin 				}
6374887Schin 				c = ' ';
6384887Schin 				/*FALLTHROUGH*/
6394887Schin 			default:
6404887Schin 				if (q)
6414887Schin 				{
6424887Schin 					q = 0;
6434887Schin 					sfprintf(op, "\">");
6444887Schin 				}
6454887Schin 				sfputc(op, c);
6464887Schin 				continue;
6474887Schin 			}
6484887Schin 			break;
6494887Schin 		}
6504887Schin 	}
6514887Schin 	sfprintf(op, "</OL>\n");
6524887Schin 	sfprintf(op, "</BODY></HTML>\n");
6534887Schin 	error_info.line = 0;
6544887Schin }
6554887Schin 
6564887Schin int
main(int argc,char ** argv)6574887Schin main(int argc, char** argv)
6584887Schin {
6594887Schin 	int		flags = 0;
6604887Schin 	Convert_f	convert = msg2html;
6614887Schin 
6624887Schin 	NoP(argc);
6634887Schin 	error_info.id = "msgcvt";
6644887Schin 	for (;;)
6654887Schin 	{
6664887Schin 		switch (optget(argv, usage))
6674887Schin 		{
6684887Schin 		case 'h':
6694887Schin 			convert = msg2html;
6704887Schin 			continue;
6714887Schin 		case 'm':
6724887Schin 			convert = html2msg;
6734887Schin 			continue;
6744887Schin 		case 'r':
6754887Schin 			flags |= MSG_RAW;
6764887Schin 			continue;
6774887Schin 		case '?':
6784887Schin 			error(ERROR_USAGE|4, "%s", opt_info.arg);
6794887Schin 			continue;
6804887Schin 		case ':':
6814887Schin 			error(2, "%s", opt_info.arg);
6824887Schin 			continue;
6834887Schin 		}
6844887Schin 		break;
6854887Schin 	}
6864887Schin 	argv += opt_info.index;
6874887Schin 	if (error_info.errors)
6884887Schin 		error(ERROR_USAGE|4, "%s", optusage(NiL));
6894887Schin 	(*convert)(sfstdin, sfstdout, flags);
6904887Schin 	return error_info.errors != 0;
6914887Schin }
692