1*0a6a1f1dSLionel Sambuc /* $NetBSD: parse.c,v 1.27 2014/07/06 18:15:34 christos Exp $ */
23e1db26aSLionel Sambuc
33e1db26aSLionel Sambuc /*-
43e1db26aSLionel Sambuc * Copyright (c) 1992, 1993
53e1db26aSLionel Sambuc * The Regents of the University of California. All rights reserved.
63e1db26aSLionel Sambuc *
73e1db26aSLionel Sambuc * This code is derived from software contributed to Berkeley by
83e1db26aSLionel Sambuc * Christos Zoulas of Cornell University.
93e1db26aSLionel Sambuc *
103e1db26aSLionel Sambuc * Redistribution and use in source and binary forms, with or without
113e1db26aSLionel Sambuc * modification, are permitted provided that the following conditions
123e1db26aSLionel Sambuc * are met:
133e1db26aSLionel Sambuc * 1. Redistributions of source code must retain the above copyright
143e1db26aSLionel Sambuc * notice, this list of conditions and the following disclaimer.
153e1db26aSLionel Sambuc * 2. Redistributions in binary form must reproduce the above copyright
163e1db26aSLionel Sambuc * notice, this list of conditions and the following disclaimer in the
173e1db26aSLionel Sambuc * documentation and/or other materials provided with the distribution.
183e1db26aSLionel Sambuc * 3. Neither the name of the University nor the names of its contributors
193e1db26aSLionel Sambuc * may be used to endorse or promote products derived from this software
203e1db26aSLionel Sambuc * without specific prior written permission.
213e1db26aSLionel Sambuc *
223e1db26aSLionel Sambuc * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
233e1db26aSLionel Sambuc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
243e1db26aSLionel Sambuc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
253e1db26aSLionel Sambuc * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
263e1db26aSLionel Sambuc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
273e1db26aSLionel Sambuc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
283e1db26aSLionel Sambuc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
293e1db26aSLionel Sambuc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
303e1db26aSLionel Sambuc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
313e1db26aSLionel Sambuc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
323e1db26aSLionel Sambuc * SUCH DAMAGE.
333e1db26aSLionel Sambuc */
343e1db26aSLionel Sambuc
353e1db26aSLionel Sambuc #include "config.h"
363e1db26aSLionel Sambuc #if !defined(lint) && !defined(SCCSID)
373e1db26aSLionel Sambuc #if 0
383e1db26aSLionel Sambuc static char sccsid[] = "@(#)parse.c 8.1 (Berkeley) 6/4/93";
393e1db26aSLionel Sambuc #else
40*0a6a1f1dSLionel Sambuc __RCSID("$NetBSD: parse.c,v 1.27 2014/07/06 18:15:34 christos Exp $");
413e1db26aSLionel Sambuc #endif
423e1db26aSLionel Sambuc #endif /* not lint && not SCCSID */
433e1db26aSLionel Sambuc
443e1db26aSLionel Sambuc /*
453e1db26aSLionel Sambuc * parse.c: parse an editline extended command
463e1db26aSLionel Sambuc *
473e1db26aSLionel Sambuc * commands are:
483e1db26aSLionel Sambuc *
493e1db26aSLionel Sambuc * bind
503e1db26aSLionel Sambuc * echotc
513e1db26aSLionel Sambuc * edit
523e1db26aSLionel Sambuc * gettc
533e1db26aSLionel Sambuc * history
543e1db26aSLionel Sambuc * settc
553e1db26aSLionel Sambuc * setty
563e1db26aSLionel Sambuc */
573e1db26aSLionel Sambuc #include "el.h"
583e1db26aSLionel Sambuc #include <stdlib.h>
593e1db26aSLionel Sambuc
603e1db26aSLionel Sambuc private const struct {
613e1db26aSLionel Sambuc const Char *name;
623e1db26aSLionel Sambuc int (*func)(EditLine *, int, const Char **);
633e1db26aSLionel Sambuc } cmds[] = {
643e1db26aSLionel Sambuc { STR("bind"), map_bind },
653e1db26aSLionel Sambuc { STR("echotc"), terminal_echotc },
663e1db26aSLionel Sambuc { STR("edit"), el_editmode },
673e1db26aSLionel Sambuc { STR("history"), hist_command },
683e1db26aSLionel Sambuc { STR("telltc"), terminal_telltc },
693e1db26aSLionel Sambuc { STR("settc"), terminal_settc },
703e1db26aSLionel Sambuc { STR("setty"), tty_stty },
713e1db26aSLionel Sambuc { NULL, NULL }
723e1db26aSLionel Sambuc };
733e1db26aSLionel Sambuc
743e1db26aSLionel Sambuc
753e1db26aSLionel Sambuc /* parse_line():
763e1db26aSLionel Sambuc * Parse a line and dispatch it
773e1db26aSLionel Sambuc */
783e1db26aSLionel Sambuc protected int
parse_line(EditLine * el,const Char * line)793e1db26aSLionel Sambuc parse_line(EditLine *el, const Char *line)
803e1db26aSLionel Sambuc {
813e1db26aSLionel Sambuc const Char **argv;
823e1db26aSLionel Sambuc int argc;
833e1db26aSLionel Sambuc TYPE(Tokenizer) *tok;
843e1db26aSLionel Sambuc
853e1db26aSLionel Sambuc tok = FUN(tok,init)(NULL);
863e1db26aSLionel Sambuc FUN(tok,str)(tok, line, &argc, &argv);
873e1db26aSLionel Sambuc argc = FUN(el,parse)(el, argc, argv);
883e1db26aSLionel Sambuc FUN(tok,end)(tok);
893e1db26aSLionel Sambuc return argc;
903e1db26aSLionel Sambuc }
913e1db26aSLionel Sambuc
923e1db26aSLionel Sambuc
933e1db26aSLionel Sambuc /* el_parse():
943e1db26aSLionel Sambuc * Command dispatcher
953e1db26aSLionel Sambuc */
963e1db26aSLionel Sambuc public int
FUN(el,parse)973e1db26aSLionel Sambuc FUN(el,parse)(EditLine *el, int argc, const Char *argv[])
983e1db26aSLionel Sambuc {
993e1db26aSLionel Sambuc const Char *ptr;
1003e1db26aSLionel Sambuc int i;
1013e1db26aSLionel Sambuc
1023e1db26aSLionel Sambuc if (argc < 1)
1033e1db26aSLionel Sambuc return -1;
1043e1db26aSLionel Sambuc ptr = Strchr(argv[0], ':');
1053e1db26aSLionel Sambuc if (ptr != NULL) {
1063e1db26aSLionel Sambuc Char *tprog;
1073e1db26aSLionel Sambuc size_t l;
1083e1db26aSLionel Sambuc
1093e1db26aSLionel Sambuc if (ptr == argv[0])
1103e1db26aSLionel Sambuc return 0;
1113e1db26aSLionel Sambuc l = (size_t)(ptr - argv[0] - 1);
1123e1db26aSLionel Sambuc tprog = el_malloc((l + 1) * sizeof(*tprog));
1133e1db26aSLionel Sambuc if (tprog == NULL)
1143e1db26aSLionel Sambuc return 0;
1153e1db26aSLionel Sambuc (void) Strncpy(tprog, argv[0], l);
1163e1db26aSLionel Sambuc tprog[l] = '\0';
1173e1db26aSLionel Sambuc ptr++;
1183e1db26aSLionel Sambuc l = (size_t)el_match(el->el_prog, tprog);
1193e1db26aSLionel Sambuc el_free(tprog);
1203e1db26aSLionel Sambuc if (!l)
1213e1db26aSLionel Sambuc return 0;
1223e1db26aSLionel Sambuc } else
1233e1db26aSLionel Sambuc ptr = argv[0];
1243e1db26aSLionel Sambuc
1253e1db26aSLionel Sambuc for (i = 0; cmds[i].name != NULL; i++)
1263e1db26aSLionel Sambuc if (Strcmp(cmds[i].name, ptr) == 0) {
1273e1db26aSLionel Sambuc i = (*cmds[i].func) (el, argc, argv);
1283e1db26aSLionel Sambuc return -i;
1293e1db26aSLionel Sambuc }
1303e1db26aSLionel Sambuc return -1;
1313e1db26aSLionel Sambuc }
1323e1db26aSLionel Sambuc
1333e1db26aSLionel Sambuc
1343e1db26aSLionel Sambuc /* parse__escape():
1353e1db26aSLionel Sambuc * Parse a string of the form ^<char> \<odigit> \<char> \U+xxxx and return
1363e1db26aSLionel Sambuc * the appropriate character or -1 if the escape is not valid
1373e1db26aSLionel Sambuc */
1383e1db26aSLionel Sambuc protected int
parse__escape(const Char ** ptr)1393e1db26aSLionel Sambuc parse__escape(const Char **ptr)
1403e1db26aSLionel Sambuc {
1413e1db26aSLionel Sambuc const Char *p;
1423e1db26aSLionel Sambuc Int c;
1433e1db26aSLionel Sambuc
1443e1db26aSLionel Sambuc p = *ptr;
1453e1db26aSLionel Sambuc
1463e1db26aSLionel Sambuc if (p[1] == 0)
1473e1db26aSLionel Sambuc return -1;
1483e1db26aSLionel Sambuc
1493e1db26aSLionel Sambuc if (*p == '\\') {
1503e1db26aSLionel Sambuc p++;
1513e1db26aSLionel Sambuc switch (*p) {
1523e1db26aSLionel Sambuc case 'a':
1533e1db26aSLionel Sambuc c = '\007'; /* Bell */
1543e1db26aSLionel Sambuc break;
1553e1db26aSLionel Sambuc case 'b':
1563e1db26aSLionel Sambuc c = '\010'; /* Backspace */
1573e1db26aSLionel Sambuc break;
1583e1db26aSLionel Sambuc case 't':
1593e1db26aSLionel Sambuc c = '\011'; /* Horizontal Tab */
1603e1db26aSLionel Sambuc break;
1613e1db26aSLionel Sambuc case 'n':
1623e1db26aSLionel Sambuc c = '\012'; /* New Line */
1633e1db26aSLionel Sambuc break;
1643e1db26aSLionel Sambuc case 'v':
1653e1db26aSLionel Sambuc c = '\013'; /* Vertical Tab */
1663e1db26aSLionel Sambuc break;
1673e1db26aSLionel Sambuc case 'f':
1683e1db26aSLionel Sambuc c = '\014'; /* Form Feed */
1693e1db26aSLionel Sambuc break;
1703e1db26aSLionel Sambuc case 'r':
1713e1db26aSLionel Sambuc c = '\015'; /* Carriage Return */
1723e1db26aSLionel Sambuc break;
1733e1db26aSLionel Sambuc case 'e':
1743e1db26aSLionel Sambuc c = '\033'; /* Escape */
1753e1db26aSLionel Sambuc break;
1763e1db26aSLionel Sambuc case 'U': /* Unicode \U+xxxx or \U+xxxxx format */
1773e1db26aSLionel Sambuc {
1783e1db26aSLionel Sambuc int i;
1793e1db26aSLionel Sambuc const Char hex[] = STR("0123456789ABCDEF");
1803e1db26aSLionel Sambuc const Char *h;
1813e1db26aSLionel Sambuc ++p;
1823e1db26aSLionel Sambuc if (*p++ != '+')
1833e1db26aSLionel Sambuc return -1;
1843e1db26aSLionel Sambuc c = 0;
1853e1db26aSLionel Sambuc for (i = 0; i < 5; ++i) {
1863e1db26aSLionel Sambuc h = Strchr(hex, *p++);
1873e1db26aSLionel Sambuc if (!h && i < 4)
1883e1db26aSLionel Sambuc return -1;
1893e1db26aSLionel Sambuc else if (h)
1903e1db26aSLionel Sambuc c = (c << 4) | ((int)(h - hex));
1913e1db26aSLionel Sambuc else
1923e1db26aSLionel Sambuc --p;
1933e1db26aSLionel Sambuc }
1943e1db26aSLionel Sambuc if (c > 0x10FFFF) /* outside valid character range */
1953e1db26aSLionel Sambuc return -1;
1963e1db26aSLionel Sambuc break;
1973e1db26aSLionel Sambuc }
1983e1db26aSLionel Sambuc case '0':
1993e1db26aSLionel Sambuc case '1':
2003e1db26aSLionel Sambuc case '2':
2013e1db26aSLionel Sambuc case '3':
2023e1db26aSLionel Sambuc case '4':
2033e1db26aSLionel Sambuc case '5':
2043e1db26aSLionel Sambuc case '6':
2053e1db26aSLionel Sambuc case '7':
2063e1db26aSLionel Sambuc {
2073e1db26aSLionel Sambuc int cnt, ch;
2083e1db26aSLionel Sambuc
2093e1db26aSLionel Sambuc for (cnt = 0, c = 0; cnt < 3; cnt++) {
2103e1db26aSLionel Sambuc ch = *p++;
2113e1db26aSLionel Sambuc if (ch < '0' || ch > '7') {
2123e1db26aSLionel Sambuc p--;
2133e1db26aSLionel Sambuc break;
2143e1db26aSLionel Sambuc }
2153e1db26aSLionel Sambuc c = (c << 3) | (ch - '0');
2163e1db26aSLionel Sambuc }
2173e1db26aSLionel Sambuc if ((c & (wint_t)0xffffff00) != (wint_t)0)
2183e1db26aSLionel Sambuc return -1;
2193e1db26aSLionel Sambuc --p;
2203e1db26aSLionel Sambuc break;
2213e1db26aSLionel Sambuc }
2223e1db26aSLionel Sambuc default:
2233e1db26aSLionel Sambuc c = *p;
2243e1db26aSLionel Sambuc break;
2253e1db26aSLionel Sambuc }
2263e1db26aSLionel Sambuc } else if (*p == '^') {
2273e1db26aSLionel Sambuc p++;
2283e1db26aSLionel Sambuc c = (*p == '?') ? '\177' : (*p & 0237);
2293e1db26aSLionel Sambuc } else
2303e1db26aSLionel Sambuc c = *p;
2313e1db26aSLionel Sambuc *ptr = ++p;
2323e1db26aSLionel Sambuc return c;
2333e1db26aSLionel Sambuc }
2343e1db26aSLionel Sambuc
2353e1db26aSLionel Sambuc /* parse__string():
2363e1db26aSLionel Sambuc * Parse the escapes from in and put the raw string out
2373e1db26aSLionel Sambuc */
2383e1db26aSLionel Sambuc protected Char *
parse__string(Char * out,const Char * in)2393e1db26aSLionel Sambuc parse__string(Char *out, const Char *in)
2403e1db26aSLionel Sambuc {
2413e1db26aSLionel Sambuc Char *rv = out;
2423e1db26aSLionel Sambuc int n;
2433e1db26aSLionel Sambuc
2443e1db26aSLionel Sambuc for (;;)
2453e1db26aSLionel Sambuc switch (*in) {
2463e1db26aSLionel Sambuc case '\0':
2473e1db26aSLionel Sambuc *out = '\0';
2483e1db26aSLionel Sambuc return rv;
2493e1db26aSLionel Sambuc
2503e1db26aSLionel Sambuc case '\\':
2513e1db26aSLionel Sambuc case '^':
2523e1db26aSLionel Sambuc if ((n = parse__escape(&in)) == -1)
2533e1db26aSLionel Sambuc return NULL;
2543e1db26aSLionel Sambuc *out++ = n;
2553e1db26aSLionel Sambuc break;
2563e1db26aSLionel Sambuc
2573e1db26aSLionel Sambuc case 'M':
2583e1db26aSLionel Sambuc if (in[1] == '-' && in[2] != '\0') {
2593e1db26aSLionel Sambuc *out++ = '\033';
2603e1db26aSLionel Sambuc in += 2;
2613e1db26aSLionel Sambuc break;
2623e1db26aSLionel Sambuc }
2633e1db26aSLionel Sambuc /*FALLTHROUGH*/
2643e1db26aSLionel Sambuc
2653e1db26aSLionel Sambuc default:
2663e1db26aSLionel Sambuc *out++ = *in++;
2673e1db26aSLionel Sambuc break;
2683e1db26aSLionel Sambuc }
2693e1db26aSLionel Sambuc }
2703e1db26aSLionel Sambuc
2713e1db26aSLionel Sambuc
2723e1db26aSLionel Sambuc /* parse_cmd():
2733e1db26aSLionel Sambuc * Return the command number for the command string given
2743e1db26aSLionel Sambuc * or -1 if one is not found
2753e1db26aSLionel Sambuc */
2763e1db26aSLionel Sambuc protected int
parse_cmd(EditLine * el,const Char * cmd)2773e1db26aSLionel Sambuc parse_cmd(EditLine *el, const Char *cmd)
2783e1db26aSLionel Sambuc {
279*0a6a1f1dSLionel Sambuc el_bindings_t *b = el->el_map.help;
280*0a6a1f1dSLionel Sambuc size_t i;
2813e1db26aSLionel Sambuc
282*0a6a1f1dSLionel Sambuc for (i = 0; i < el->el_map.nfunc; i++)
283*0a6a1f1dSLionel Sambuc if (Strcmp(b[i].name, cmd) == 0)
284*0a6a1f1dSLionel Sambuc return b[i].func;
2853e1db26aSLionel Sambuc return -1;
2863e1db26aSLionel Sambuc }
287