/*	$NetBSD: parse.c,v 1.42 2019/07/23 10:18:52 christos Exp $	*/

/*-
 * Copyright (c) 1992, 1993
 *	The Regents of the University of California.  All rights reserved.
 *
 * This code is derived from software contributed to Berkeley by
 * Christos Zoulas of Cornell University.
 *
 * 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 "config.h"
#if !defined(lint) && !defined(SCCSID)
#if 0
static char sccsid[] = "@(#)parse.c	8.1 (Berkeley) 6/4/93";
#else
__RCSID("$NetBSD: parse.c,v 1.42 2019/07/23 10:18:52 christos Exp $");
#endif
#endif /* not lint && not SCCSID */

/*
 * parse.c: parse an editline extended command
 *
 * commands are:
 *
 *	bind
 *	echotc
 *	edit
 *	gettc
 *	history
 *	settc
 *	setty
 */
#include <stdlib.h>
#include <string.h>

#include "el.h"
#include "parse.h"

static const struct {
	const wchar_t *name;
	int (*func)(EditLine *, int, const wchar_t **);
} cmds[] = {
	{ L"bind",		map_bind	},
	{ L"echotc",		terminal_echotc	},
	{ L"edit",		el_editmode	},
	{ L"history",		hist_command	},
	{ L"telltc",		terminal_telltc	},
	{ L"settc",		terminal_settc	},
	{ L"setty",		tty_stty	},
	{ NULL,			NULL		}
};


/* parse_line():
 *	Parse a line and dispatch it
 */
libedit_private int
parse_line(EditLine *el, const wchar_t *line)
{
	const wchar_t **argv;
	int argc;
	TokenizerW *tok;

	tok = tok_winit(NULL);
	tok_wstr(tok, line, &argc, &argv);
	argc = el_wparse(el, argc, argv);
	tok_wend(tok);
	return argc;
}


/* el_parse():
 *	Command dispatcher
 */
int
el_wparse(EditLine *el, int argc, const wchar_t *argv[])
{
	const wchar_t *ptr;
	int i;

	if (argc < 1)
		return -1;
	ptr = wcschr(argv[0], L':');
	if (ptr != NULL) {
		wchar_t *tprog;
		size_t l;

		if (ptr == argv[0])
			return 0;
		l = (size_t)(ptr - argv[0]);
		tprog = el_calloc(l + 1, sizeof(*tprog));
		if (tprog == NULL)
			return 0;
		(void) wcsncpy(tprog, argv[0], l);
		tprog[l] = '\0';
		ptr++;
		l = (size_t)el_match(el->el_prog, tprog);
		el_free(tprog);
		if (!l)
			return 0;
	} else
		ptr = argv[0];

	for (i = 0; cmds[i].name != NULL; i++)
		if (wcscmp(cmds[i].name, ptr) == 0) {
			i = (*cmds[i].func) (el, argc, argv);
			return -i;
		}
	return -1;
}


/* parse__escape():
 *	Parse a string of the form ^<char> \<odigit> \<char> \U+xxxx and return
 *	the appropriate character or -1 if the escape is not valid
 */
libedit_private int
parse__escape(const wchar_t **ptr)
{
	const wchar_t *p;
	wint_t c;

	p = *ptr;

	if (p[1] == 0)
		return -1;

	if (*p == '\\') {
		p++;
		switch (*p) {
		case 'a':
			c = '\007';	/* Bell */
			break;
		case 'b':
			c = '\010';	/* Backspace */
			break;
		case 't':
			c = '\011';	/* Horizontal Tab */
			break;
		case 'n':
			c = '\012';	/* New Line */
			break;
		case 'v':
			c = '\013';	/* Vertical Tab */
			break;
		case 'f':
			c = '\014';	/* Form Feed */
			break;
		case 'r':
			c = '\015';	/* Carriage Return */
			break;
		case 'e':
			c = '\033';	/* Escape */
			break;
		case 'U':		/* Unicode \U+xxxx or \U+xxxxx format */
		{
			int i;
			const wchar_t hex[] = L"0123456789ABCDEF";
			const wchar_t *h;
			++p;
			if (*p++ != '+')
				return -1;
			c = 0;
			for (i = 0; i < 5; ++i) {
				h = wcschr(hex, *p++);
				if (!h && i < 4)
					return -1;
				else if (h)
					c = (c << 4) | ((int)(h - hex));
				else
					--p;
			}
			if (c > 0x10FFFF) /* outside valid character range */
				return -1;
			break;
		}
		case '0':
		case '1':
		case '2':
		case '3':
		case '4':
		case '5':
		case '6':
		case '7':
		{
			int cnt, ch;

			for (cnt = 0, c = 0; cnt < 3; cnt++) {
				ch = *p++;
				if (ch < '0' || ch > '7') {
					p--;
					break;
				}
				c = (c << 3) | (ch - '0');
			}
			if ((c & (wint_t)0xffffff00) != (wint_t)0)
				return -1;
			--p;
			break;
		}
		default:
			c = *p;
			break;
		}
	} else if (*p == '^') {
		p++;
		c = (*p == '?') ? '\177' : (*p & 0237);
	} else
		c = *p;
	*ptr = ++p;
	return c;
}

/* parse__string():
 *	Parse the escapes from in and put the raw string out
 */
libedit_private wchar_t *
parse__string(wchar_t *out, const wchar_t *in)
{
	wchar_t *rv = out;
	int n;

	for (;;)
		switch (*in) {
		case '\0':
			*out = '\0';
			return rv;

		case '\\':
		case '^':
			if ((n = parse__escape(&in)) == -1)
				return NULL;
			*out++ = (wchar_t)n;
			break;

		case 'M':
			if (in[1] == '-' && in[2] != '\0') {
				*out++ = '\033';
				in += 2;
				break;
			}
			/*FALLTHROUGH*/

		default:
			*out++ = *in++;
			break;
		}
}


/* parse_cmd():
 *	Return the command number for the command string given
 *	or -1 if one is not found
 */
libedit_private int
parse_cmd(EditLine *el, const wchar_t *cmd)
{
	el_bindings_t *b = el->el_map.help;
	size_t i;

	for (i = 0; i < el->el_map.nfunc; i++)
		if (wcscmp(b[i].name, cmd) == 0)
			return b[i].func;
	return -1;
}
