--- /dev/null	2013-02-23 16:58:58.000000000 +0000
+++ new/usr/src/cmd/iconv/scanner.c	2013-02-23 16:58:58.610633496 +0000
@@ -0,0 +1,345 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2010 Nexenta Systems, Inc.  All rights reserved.
+ * Copyright 2013 David Hoeppner.  All rights reserved.
+ */
+
+/*
+ * Functions to charmap .
+ */
+
+#include <assert.h>
+
+#include "iconv.h"
+#include "parser.tab.h"
+
+/*
+ * Charmap specific.
+ */
+int		com_char = '#';
+int		esc_char = '\\';
+int		mb_cur_max = 1;
+int		mb_cur_min = 1;
+
+int		lineno = 1;
+static FILE	*input = stdin;
+static const char *filename = "<stdin>";
+static int	escaped = 0;
+static int	instring = 0;
+static int	nextline;
+
+/*
+ * Tokens.
+ */
+static char	*token = NULL;
+static int	tokidx;
+static int	toksz = 0;
+static int	hadtok = 0;
+
+/*
+ * Wide strings.
+ */
+static wchar_t	*widestr = NULL;
+static int	wideidx = 0;
+static int	widesz = 0;
+
+/*
+ * Keywords related.
+ */
+static int	category = T_END;
+
+static struct token {
+	int	id;
+	const char *name;
+} keywords[] = {
+	{ T_COM_CHAR,		"comment_char" },
+	{ -1, NULL },
+};
+
+/*
+ * Charmap reserved keywords.
+ */
+static struct token symwords[] = {
+	{ T_COM_CHAR,		"comment_char" },
+	{ -1, NULL },
+};
+
+/*
+ * Reset the scanner variables and open the supplied charmap file.
+ */
+void
+reset_scanner(const char *fname)
+{
+	input = fopen(fname, "r");
+	if (input == NULL) {
+		perror("fopen");
+		exit(4);
+	}
+
+	filename = fname;
+	com_char = '#';
+	esc_char = '\\';
+	instring = 0;
+	escaped = 0;
+	lineno = 1;
+	nextline = 1;
+	tokidx = 0;
+	wideidx = 0;
+}
+
+static int
+scanc(void)
+{
+	int	c;
+
+	c = getc(input);
+	lineno = nextline;
+	if (c == '\n') {
+		nextline++;
+	}
+
+	return (c);
+}
+
+static void
+unscanc(int c)
+{
+	if (c == '\n') {
+		nextline--;
+	}
+
+	if (ungetc(c, input) < 0) {
+		yyerror(_("ungetc failed"));
+	}
+}
+
+void
+add_tok(int c)
+{
+	if ((tokidx + 1) >= toksz) {
+		toksz += 64;
+
+		if ((token = realloc(token, toksz)) == NULL) {
+			yyerror(_("out of memory"));
+			tokidx = 0;
+			toksz = 0;
+			return;
+		}
+	}
+
+	token[tokidx++] = (char)c;
+	token[tokidx] = 0;
+}
+
+int
+get_escaped(int c)
+{
+	switch (c) {
+	case 'n':
+		return ('\n');
+	case 'r':
+		return ('\r');
+	case 't':
+		return ('\t');
+	case 'f':
+		return ('\f');
+	case 'v':
+		return ('\v');
+	case 'b':
+		return ('\b');
+	case 'a':
+		return ('\a');
+	default:
+		return (c);
+	}
+}
+
+int
+get_symbol(void)
+{
+	int	c;
+
+	while ((c = scanc()) != EOF) {
+		if (escaped == 1) {
+			escaped = 0;
+			if (c == '\n') {
+				continue;
+			}
+
+			add_tok(get_escaped(c));
+			continue;
+		}
+
+		if (c == esc_char) {
+			escaped = 1;
+			continue;
+		}
+
+		if (c == '\n') {	/* Well that's strange! */
+			yyerror(_("unterminated symbolic name"));
+			continue;
+		}
+
+		if (c == '>') {		/* End of symbol */
+			/*
+			 * This restarts the token from the beginning
+			 * the next time we scan a character.  (This
+			 * token is complete.)
+			 */
+			if (token == NULL) {
+				yyerror(_("missing symbolic name"));
+				return (T_NULL);
+			}
+
+			tokidx = 0;
+
+			/* XXX */
+			if (category == T_END) {
+
+			}
+
+			/* XXX */
+
+			/* Its an undefined symbol */
+			yylval.token = strdup(token);
+			token = NULL;
+			toksz = 0;
+			tokidx = 0;
+
+			return (T_SYMBOL);
+		}
+
+		add_tok(c);
+	}
+
+	yyerror(_("unterminated symbolic name"));
+
+	return (EOF);
+}
+
+static int
+consume_token(void)
+{
+	/* XXX */
+
+	printf("XXX consume_token XXX\n");
+
+	return (T_NAME);
+}
+
+void
+scan_to_eol(void)
+{
+	int	c;
+
+	while ((c = scanc()) != '\n') {
+		if (c == EOF) {
+			/* end of file without newline! */
+			errf(_("missing newline"));
+			return;
+		}
+	}
+
+	assert(c == '\n');
+}
+
+int
+yylex(void)
+{
+	int	c;
+printf("yylex\n");
+	while ((c = scanc()) != EOF) {
+
+		/* If it is the escape character itself note it */
+		if (c == esc_char) {
+			escaped = 1;
+			continue;
+		}
+
+		/* Remove from the comment character to end of line */
+		if (c == com_char) {
+			while (c != '\n') {
+				if ((c = scanc()) == EOF) {
+					/* End of file without newline */
+					return (EOF);
+				}
+			}
+
+			assert(c == '\n');
+
+printf("NEWLINE\n");
+			if (hadtok == 0) {
+				/*
+				 * If there were no tokens on this line,
+				 * then just pretend it didn't exist at all.
+				 */
+				continue;
+			}
+
+			hadtok = 0;
+			return (T_NL);
+		}
+
+		if (strchr(" \t\n;()<>,\"", c) && (tokidx != 0)) {
+			/*
+			 * These are all token delimiters.  If there
+			 * is a token already in progress, we need to
+			 * process it.
+			 */
+			unscanc(c);
+			return (consume_token());
+		}
+
+		switch (c) {
+		case '\n':
+			return (T_NL);
+		case '>':
+			hadtok = 1;
+			return (T_GT);
+		case '<':
+			/* Symbol start! */
+			hadtok = 1;
+			return (get_symbol());
+		case ' ':
+		case '\t':
+			/* Whitespace, just ignore */
+			continue;
+		case '"':
+			hadtok = 1;
+			instring = 1;
+			return (T_QUOTE);
+		default:
+			hadtok = 1;
+			add_tok(c);
+			continue;
+		}
+	}
+
+	return (EOF);
+}
+
+void
+yyerror(const char *msg)
+{
+	(void) fprintf(stderr, _("%s: %d: error: %s\n"),
+	    filename, lineno, msg);
+	exit(4);
+}
+
+void
+errf(const char *fmt, ...)
+{
+	/* XXX */
+
+	exit(4);
+}
