1313981Spfg/* $NetBSD: parse.c,v 1.35 2016/02/17 19:47:49 christos Exp $ */ 2276881Sbapt 31573Srgrimes/*- 41573Srgrimes * Copyright (c) 1992, 1993 51573Srgrimes * The Regents of the University of California. All rights reserved. 61573Srgrimes * 71573Srgrimes * This code is derived from software contributed to Berkeley by 81573Srgrimes * Christos Zoulas of Cornell University. 91573Srgrimes * 101573Srgrimes * Redistribution and use in source and binary forms, with or without 111573Srgrimes * modification, are permitted provided that the following conditions 121573Srgrimes * are met: 131573Srgrimes * 1. Redistributions of source code must retain the above copyright 141573Srgrimes * notice, this list of conditions and the following disclaimer. 151573Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 161573Srgrimes * notice, this list of conditions and the following disclaimer in the 171573Srgrimes * documentation and/or other materials provided with the distribution. 18148834Sstefanf * 3. Neither the name of the University nor the names of its contributors 191573Srgrimes * may be used to endorse or promote products derived from this software 201573Srgrimes * without specific prior written permission. 211573Srgrimes * 221573Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 231573Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 241573Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 251573Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 261573Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 271573Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 281573Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 291573Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 301573Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 311573Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 321573Srgrimes * SUCH DAMAGE. 331573Srgrimes */ 341573Srgrimes 35276881Sbapt#include "config.h" 361573Srgrimes#if !defined(lint) && !defined(SCCSID) 37276881Sbapt#if 0 381573Srgrimesstatic char sccsid[] = "@(#)parse.c 8.1 (Berkeley) 6/4/93"; 39276881Sbapt#else 40313981Spfg__RCSID("$NetBSD: parse.c,v 1.35 2016/02/17 19:47:49 christos Exp $"); 41276881Sbapt#endif 421573Srgrimes#endif /* not lint && not SCCSID */ 4384260Sobrien#include <sys/cdefs.h> 4484260Sobrien__FBSDID("$FreeBSD: stable/11/lib/libedit/parse.c 313981 2017-02-20 03:33:59Z pfg $"); 451573Srgrimes 461573Srgrimes/* 471573Srgrimes * parse.c: parse an editline extended command 481573Srgrimes * 491573Srgrimes * commands are: 501573Srgrimes * 511573Srgrimes * bind 521573Srgrimes * echotc 5384260Sobrien * edit 541573Srgrimes * gettc 5526926Smsmith * history 5626926Smsmith * settc 5726926Smsmith * setty 581573Srgrimes */ 5984260Sobrien#include <stdlib.h> 60313981Spfg#include <string.h> 611573Srgrimes 62313981Spfg#include "el.h" 63313981Spfg#include "parse.h" 64313981Spfg 6584260Sobrienprivate const struct { 66276881Sbapt const Char *name; 67276881Sbapt int (*func)(EditLine *, int, const Char **); 681573Srgrimes} cmds[] = { 69313981Spfg { STR("bind"), map_bind }, 70276881Sbapt { STR("echotc"), terminal_echotc }, 71313981Spfg { STR("edit"), el_editmode }, 72276881Sbapt { STR("history"), hist_command }, 73276881Sbapt { STR("telltc"), terminal_telltc }, 74276881Sbapt { STR("settc"), terminal_settc }, 75276881Sbapt { STR("setty"), tty_stty }, 76276881Sbapt { NULL, NULL } 771573Srgrimes}; 781573Srgrimes 791573Srgrimes 801573Srgrimes/* parse_line(): 811573Srgrimes * Parse a line and dispatch it 821573Srgrimes */ 831573Srgrimesprotected int 84276881Sbaptparse_line(EditLine *el, const Char *line) 851573Srgrimes{ 86276881Sbapt const Char **argv; 8784260Sobrien int argc; 88276881Sbapt TYPE(Tokenizer) *tok; 891573Srgrimes 90276881Sbapt tok = FUN(tok,init)(NULL); 91276881Sbapt FUN(tok,str)(tok, line, &argc, &argv); 92276881Sbapt argc = FUN(el,parse)(el, argc, argv); 93276881Sbapt FUN(tok,end)(tok); 94276881Sbapt return argc; 951573Srgrimes} 961573Srgrimes 9784260Sobrien 981573Srgrimes/* el_parse(): 991573Srgrimes * Command dispatcher 1001573Srgrimes */ 1011573Srgrimespublic int 102276881SbaptFUN(el,parse)(EditLine *el, int argc, const Char *argv[]) 1031573Srgrimes{ 104276881Sbapt const Char *ptr; 10584260Sobrien int i; 1061573Srgrimes 10784260Sobrien if (argc < 1) 108276881Sbapt return -1; 109276881Sbapt ptr = Strchr(argv[0], ':'); 11084260Sobrien if (ptr != NULL) { 111276881Sbapt Char *tprog; 11284260Sobrien size_t l; 1131573Srgrimes 11484260Sobrien if (ptr == argv[0]) 115276881Sbapt return 0; 116276881Sbapt l = (size_t)(ptr - argv[0] - 1); 117276881Sbapt tprog = el_malloc((l + 1) * sizeof(*tprog)); 11884260Sobrien if (tprog == NULL) 119276881Sbapt return 0; 120276881Sbapt (void) Strncpy(tprog, argv[0], l); 12184260Sobrien tprog[l] = '\0'; 12284260Sobrien ptr++; 123276881Sbapt l = (size_t)el_match(el->el_prog, tprog); 12484260Sobrien el_free(tprog); 12584260Sobrien if (!l) 126276881Sbapt return 0; 12784260Sobrien } else 12884260Sobrien ptr = argv[0]; 1291573Srgrimes 13084260Sobrien for (i = 0; cmds[i].name != NULL; i++) 131276881Sbapt if (Strcmp(cmds[i].name, ptr) == 0) { 13284260Sobrien i = (*cmds[i].func) (el, argc, argv); 133276881Sbapt return -i; 13484260Sobrien } 135276881Sbapt return -1; 1361573Srgrimes} 1371573Srgrimes 1381573Srgrimes 1391573Srgrimes/* parse__escape(): 140276881Sbapt * Parse a string of the form ^<char> \<odigit> \<char> \U+xxxx and return 1411573Srgrimes * the appropriate character or -1 if the escape is not valid 1421573Srgrimes */ 1431573Srgrimesprotected int 144276881Sbaptparse__escape(const Char **ptr) 1451573Srgrimes{ 146276881Sbapt const Char *p; 147313981Spfg wint_t c; 1481573Srgrimes 14984260Sobrien p = *ptr; 1501573Srgrimes 15184260Sobrien if (p[1] == 0) 152276881Sbapt return -1; 1531573Srgrimes 15484260Sobrien if (*p == '\\') { 15584260Sobrien p++; 15684260Sobrien switch (*p) { 15784260Sobrien case 'a': 15884260Sobrien c = '\007'; /* Bell */ 15984260Sobrien break; 16084260Sobrien case 'b': 16184260Sobrien c = '\010'; /* Backspace */ 16284260Sobrien break; 16384260Sobrien case 't': 16484260Sobrien c = '\011'; /* Horizontal Tab */ 16584260Sobrien break; 16684260Sobrien case 'n': 16784260Sobrien c = '\012'; /* New Line */ 16884260Sobrien break; 16984260Sobrien case 'v': 17084260Sobrien c = '\013'; /* Vertical Tab */ 17184260Sobrien break; 17284260Sobrien case 'f': 17384260Sobrien c = '\014'; /* Form Feed */ 17484260Sobrien break; 17584260Sobrien case 'r': 17684260Sobrien c = '\015'; /* Carriage Return */ 17784260Sobrien break; 17884260Sobrien case 'e': 17984260Sobrien c = '\033'; /* Escape */ 18084260Sobrien break; 181276881Sbapt case 'U': /* Unicode \U+xxxx or \U+xxxxx format */ 182276881Sbapt { 183276881Sbapt int i; 184276881Sbapt const Char hex[] = STR("0123456789ABCDEF"); 185276881Sbapt const Char *h; 186276881Sbapt ++p; 187276881Sbapt if (*p++ != '+') 188276881Sbapt return -1; 189276881Sbapt c = 0; 190276881Sbapt for (i = 0; i < 5; ++i) { 191276881Sbapt h = Strchr(hex, *p++); 192276881Sbapt if (!h && i < 4) 193276881Sbapt return -1; 194276881Sbapt else if (h) 195276881Sbapt c = (c << 4) | ((int)(h - hex)); 196276881Sbapt else 197276881Sbapt --p; 198276881Sbapt } 199276881Sbapt if (c > 0x10FFFF) /* outside valid character range */ 200276881Sbapt return -1; 201276881Sbapt break; 202276881Sbapt } 20384260Sobrien case '0': 20484260Sobrien case '1': 20584260Sobrien case '2': 20684260Sobrien case '3': 20784260Sobrien case '4': 20884260Sobrien case '5': 20984260Sobrien case '6': 21084260Sobrien case '7': 21184260Sobrien { 21284260Sobrien int cnt, ch; 2131573Srgrimes 21484260Sobrien for (cnt = 0, c = 0; cnt < 3; cnt++) { 21584260Sobrien ch = *p++; 21684260Sobrien if (ch < '0' || ch > '7') { 21784260Sobrien p--; 21884260Sobrien break; 21984260Sobrien } 22084260Sobrien c = (c << 3) | (ch - '0'); 22184260Sobrien } 222276881Sbapt if ((c & (wint_t)0xffffff00) != (wint_t)0) 223276881Sbapt return -1; 22484260Sobrien --p; 2251573Srgrimes break; 2261573Srgrimes } 22784260Sobrien default: 22884260Sobrien c = *p; 22984260Sobrien break; 23084260Sobrien } 231148834Sstefanf } else if (*p == '^') { 23284260Sobrien p++; 23384260Sobrien c = (*p == '?') ? '\177' : (*p & 0237); 23484260Sobrien } else 23584260Sobrien c = *p; 23684260Sobrien *ptr = ++p; 237276881Sbapt return c; 2381573Srgrimes} 239148834Sstefanf 2401573Srgrimes/* parse__string(): 2411573Srgrimes * Parse the escapes from in and put the raw string out 2421573Srgrimes */ 243276881Sbaptprotected Char * 244276881Sbaptparse__string(Char *out, const Char *in) 2451573Srgrimes{ 246276881Sbapt Char *rv = out; 24784260Sobrien int n; 2481573Srgrimes 24984260Sobrien for (;;) 25084260Sobrien switch (*in) { 25184260Sobrien case '\0': 25284260Sobrien *out = '\0'; 253276881Sbapt return rv; 2541573Srgrimes 25584260Sobrien case '\\': 25684260Sobrien case '^': 25784260Sobrien if ((n = parse__escape(&in)) == -1) 258276881Sbapt return NULL; 259313981Spfg *out++ = (Char)n; 26084260Sobrien break; 26184260Sobrien 262148834Sstefanf case 'M': 263148834Sstefanf if (in[1] == '-' && in[2] != '\0') { 264148834Sstefanf *out++ = '\033'; 265148834Sstefanf in += 2; 266148834Sstefanf break; 267148834Sstefanf } 268148834Sstefanf /*FALLTHROUGH*/ 269148834Sstefanf 27084260Sobrien default: 27184260Sobrien *out++ = *in++; 27284260Sobrien break; 27384260Sobrien } 2741573Srgrimes} 2751573Srgrimes 27684260Sobrien 2771573Srgrimes/* parse_cmd(): 2781573Srgrimes * Return the command number for the command string given 2791573Srgrimes * or -1 if one is not found 2801573Srgrimes */ 2811573Srgrimesprotected int 282276881Sbaptparse_cmd(EditLine *el, const Char *cmd) 2831573Srgrimes{ 284276881Sbapt el_bindings_t *b = el->el_map.help; 285276881Sbapt size_t i; 2861573Srgrimes 287276881Sbapt for (i = 0; i < el->el_map.nfunc; i++) 288276881Sbapt if (Strcmp(b[i].name, cmd) == 0) 289276881Sbapt return b[i].func; 290276881Sbapt return -1; 2911573Srgrimes} 292