/* $NetBSD: parse.c,v 1.42 2019/07/23 10:18:52 christos Exp $ */12/*-3* Copyright (c) 1992, 19934* The Regents of the University of California. All rights reserved.5*6* This code is derived from software contributed to Berkeley by7* Christos Zoulas of Cornell University.8*9* Redistribution and use in source and binary forms, with or without10* modification, are permitted provided that the following conditions11* are met:12* 1. Redistributions of source code must retain the above copyright13* notice, this list of conditions and the following disclaimer.14* 2. Redistributions in binary form must reproduce the above copyright15* notice, this list of conditions and the following disclaimer in the16* documentation and/or other materials provided with the distribution.17* 3. Neither the name of the University nor the names of its contributors18* may be used to endorse or promote products derived from this software19* without specific prior written permission.20*21* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND22* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE23* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE24* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE25* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL26* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS27* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)28* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT29* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY30* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF31* SUCH DAMAGE.32*/3334#include "config.h"35#if !defined(lint) && !defined(SCCSID)36#if 037static char sccsid[] = "@(#)parse.c 8.1 (Berkeley) 6/4/93";38#else39__RCSID("$NetBSD: parse.c,v 1.42 2019/07/23 10:18:52 christos Exp $");40#endif41#endif /* not lint && not SCCSID */4243/*44* parse.c: parse an editline extended command45*46* commands are:47*48* bind49* echotc50* edit51* gettc52* history53* settc54* setty55*/56#include <stdlib.h>57#include <string.h>5859#include "el.h"60#include "parse.h"6162static const struct {63const wchar_t *name;64int (*func)(EditLine *, int, const wchar_t **);65} cmds[] = {66{ L"bind", map_bind },67{ L"echotc", terminal_echotc },68{ L"edit", el_editmode },69{ L"history", hist_command },70{ L"telltc", terminal_telltc },71{ L"settc", terminal_settc },72{ L"setty", tty_stty },73{ NULL, NULL }74};757677/* parse_line():78* Parse a line and dispatch it79*/80libedit_private int81parse_line(EditLine *el, const wchar_t *line)82{83const wchar_t **argv;84int argc;85TokenizerW *tok;8687tok = tok_winit(NULL);88tok_wstr(tok, line, &argc, &argv);89argc = el_wparse(el, argc, argv);90tok_wend(tok);91return argc;92}939495/* el_parse():96* Command dispatcher97*/98int99el_wparse(EditLine *el, int argc, const wchar_t *argv[])100{101const wchar_t *ptr;102int i;103104if (argc < 1)105return -1;106ptr = wcschr(argv[0], L':');107if (ptr != NULL) {108wchar_t *tprog;109size_t l;110111if (ptr == argv[0])112return 0;113l = (size_t)(ptr - argv[0]);114tprog = el_calloc(l + 1, sizeof(*tprog));115if (tprog == NULL)116return 0;117(void) wcsncpy(tprog, argv[0], l);118tprog[l] = '\0';119ptr++;120l = (size_t)el_match(el->el_prog, tprog);121el_free(tprog);122if (!l)123return 0;124} else125ptr = argv[0];126127for (i = 0; cmds[i].name != NULL; i++)128if (wcscmp(cmds[i].name, ptr) == 0) {129i = (*cmds[i].func) (el, argc, argv);130return -i;131}132return -1;133}134135136/* parse__escape():137* Parse a string of the form ^<char> \<odigit> \<char> \U+xxxx and return138* the appropriate character or -1 if the escape is not valid139*/140libedit_private int141parse__escape(const wchar_t **ptr)142{143const wchar_t *p;144wint_t c;145146p = *ptr;147148if (p[1] == 0)149return -1;150151if (*p == '\\') {152p++;153switch (*p) {154case 'a':155c = '\007'; /* Bell */156break;157case 'b':158c = '\010'; /* Backspace */159break;160case 't':161c = '\011'; /* Horizontal Tab */162break;163case 'n':164c = '\012'; /* New Line */165break;166case 'v':167c = '\013'; /* Vertical Tab */168break;169case 'f':170c = '\014'; /* Form Feed */171break;172case 'r':173c = '\015'; /* Carriage Return */174break;175case 'e':176c = '\033'; /* Escape */177break;178case 'U': /* Unicode \U+xxxx or \U+xxxxx format */179{180int i;181const wchar_t hex[] = L"0123456789ABCDEF";182const wchar_t *h;183++p;184if (*p++ != '+')185return -1;186c = 0;187for (i = 0; i < 5; ++i) {188h = wcschr(hex, *p++);189if (!h && i < 4)190return -1;191else if (h)192c = (c << 4) | ((int)(h - hex));193else194--p;195}196if (c > 0x10FFFF) /* outside valid character range */197return -1;198break;199}200case '0':201case '1':202case '2':203case '3':204case '4':205case '5':206case '6':207case '7':208{209int cnt, ch;210211for (cnt = 0, c = 0; cnt < 3; cnt++) {212ch = *p++;213if (ch < '0' || ch > '7') {214p--;215break;216}217c = (c << 3) | (ch - '0');218}219if ((c & (wint_t)0xffffff00) != (wint_t)0)220return -1;221--p;222break;223}224default:225c = *p;226break;227}228} else if (*p == '^') {229p++;230c = (*p == '?') ? '\177' : (*p & 0237);231} else232c = *p;233*ptr = ++p;234return c;235}236237/* parse__string():238* Parse the escapes from in and put the raw string out239*/240libedit_private wchar_t *241parse__string(wchar_t *out, const wchar_t *in)242{243wchar_t *rv = out;244int n;245246for (;;)247switch (*in) {248case '\0':249*out = '\0';250return rv;251252case '\\':253case '^':254if ((n = parse__escape(&in)) == -1)255return NULL;256*out++ = (wchar_t)n;257break;258259case 'M':260if (in[1] == '-' && in[2] != '\0') {261*out++ = '\033';262in += 2;263break;264}265/*FALLTHROUGH*/266267default:268*out++ = *in++;269break;270}271}272273274/* parse_cmd():275* Return the command number for the command string given276* or -1 if one is not found277*/278libedit_private int279parse_cmd(EditLine *el, const wchar_t *cmd)280{281el_bindings_t *b = el->el_map.help;282size_t i;283284for (i = 0; i < el->el_map.nfunc; i++)285if (wcscmp(b[i].name, cmd) == 0)286return b[i].func;287return -1;288}289290291