11573Srgrimes/*- 21573Srgrimes * Copyright (c) 1992, 1993 31573Srgrimes * The Regents of the University of California. All rights reserved. 41573Srgrimes * 51573Srgrimes * This code is derived from software contributed to Berkeley by 61573Srgrimes * Christos Zoulas of Cornell University. 71573Srgrimes * 81573Srgrimes * Redistribution and use in source and binary forms, with or without 91573Srgrimes * modification, are permitted provided that the following conditions 101573Srgrimes * are met: 111573Srgrimes * 1. Redistributions of source code must retain the above copyright 121573Srgrimes * notice, this list of conditions and the following disclaimer. 131573Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 141573Srgrimes * notice, this list of conditions and the following disclaimer in the 151573Srgrimes * documentation and/or other materials provided with the distribution. 16148834Sstefanf * 3. Neither the name of the University nor the names of its contributors 171573Srgrimes * may be used to endorse or promote products derived from this software 181573Srgrimes * without specific prior written permission. 191573Srgrimes * 201573Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 211573Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 221573Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 231573Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 241573Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 251573Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 261573Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 271573Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 281573Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 291573Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 301573Srgrimes * SUCH DAMAGE. 3184260Sobrien * 32148834Sstefanf * $NetBSD: parse.c,v 1.22 2005/05/29 04:58:15 lukem Exp $ 331573Srgrimes */ 341573Srgrimes 351573Srgrimes#if !defined(lint) && !defined(SCCSID) 361573Srgrimesstatic char sccsid[] = "@(#)parse.c 8.1 (Berkeley) 6/4/93"; 371573Srgrimes#endif /* not lint && not SCCSID */ 3884260Sobrien#include <sys/cdefs.h> 3984260Sobrien__FBSDID("$FreeBSD$"); 401573Srgrimes 411573Srgrimes/* 421573Srgrimes * parse.c: parse an editline extended command 431573Srgrimes * 441573Srgrimes * commands are: 451573Srgrimes * 461573Srgrimes * bind 471573Srgrimes * echotc 4884260Sobrien * edit 491573Srgrimes * gettc 5026926Smsmith * history 5126926Smsmith * settc 5226926Smsmith * setty 531573Srgrimes */ 541573Srgrimes#include "sys.h" 551573Srgrimes#include "el.h" 5684260Sobrien#include <stdlib.h> 571573Srgrimes 5884260Sobrienprivate const struct { 59148834Sstefanf const char *name; 60148834Sstefanf int (*func)(EditLine *, int, const char **); 611573Srgrimes} cmds[] = { 6284260Sobrien { "bind", map_bind }, 6384260Sobrien { "echotc", term_echotc }, 6484260Sobrien { "edit", el_editmode }, 65148834Sstefanf { "history", hist_command }, 6684260Sobrien { "telltc", term_telltc }, 6784260Sobrien { "settc", term_settc }, 6884260Sobrien { "setty", tty_stty }, 6984260Sobrien { NULL, NULL } 701573Srgrimes}; 711573Srgrimes 721573Srgrimes 731573Srgrimes/* parse_line(): 741573Srgrimes * Parse a line and dispatch it 751573Srgrimes */ 761573Srgrimesprotected int 7784260Sobrienparse_line(EditLine *el, const char *line) 781573Srgrimes{ 79148834Sstefanf const char **argv; 8084260Sobrien int argc; 8184260Sobrien Tokenizer *tok; 821573Srgrimes 8384260Sobrien tok = tok_init(NULL); 84148834Sstefanf tok_str(tok, line, &argc, &argv); 8584260Sobrien argc = el_parse(el, argc, argv); 8684260Sobrien tok_end(tok); 8784260Sobrien return (argc); 881573Srgrimes} 891573Srgrimes 9084260Sobrien 911573Srgrimes/* el_parse(): 921573Srgrimes * Command dispatcher 931573Srgrimes */ 941573Srgrimespublic int 95148834Sstefanfel_parse(EditLine *el, int argc, const char *argv[]) 961573Srgrimes{ 97148834Sstefanf const char *ptr; 9884260Sobrien int i; 991573Srgrimes 10084260Sobrien if (argc < 1) 10184260Sobrien return (-1); 10284260Sobrien ptr = strchr(argv[0], ':'); 10384260Sobrien if (ptr != NULL) { 10484260Sobrien char *tprog; 10584260Sobrien size_t l; 1061573Srgrimes 10784260Sobrien if (ptr == argv[0]) 10884260Sobrien return (0); 10984260Sobrien l = ptr - argv[0] - 1; 11084260Sobrien tprog = (char *) el_malloc(l + 1); 11184260Sobrien if (tprog == NULL) 11284260Sobrien return (0); 11384260Sobrien (void) strncpy(tprog, argv[0], l); 11484260Sobrien tprog[l] = '\0'; 11584260Sobrien ptr++; 11684260Sobrien l = el_match(el->el_prog, tprog); 11784260Sobrien el_free(tprog); 11884260Sobrien if (!l) 11984260Sobrien return (0); 12084260Sobrien } else 12184260Sobrien ptr = argv[0]; 1221573Srgrimes 12384260Sobrien for (i = 0; cmds[i].name != NULL; i++) 12484260Sobrien if (strcmp(cmds[i].name, ptr) == 0) { 12584260Sobrien i = (*cmds[i].func) (el, argc, argv); 12684260Sobrien return (-i); 12784260Sobrien } 12884260Sobrien return (-1); 1291573Srgrimes} 1301573Srgrimes 1311573Srgrimes 1321573Srgrimes/* parse__escape(): 1331573Srgrimes * Parse a string of the form ^<char> \<odigit> \<char> and return 1341573Srgrimes * the appropriate character or -1 if the escape is not valid 1351573Srgrimes */ 1361573Srgrimesprotected int 137148834Sstefanfparse__escape(const char **ptr) 1381573Srgrimes{ 13984260Sobrien const char *p; 14084260Sobrien int c; 1411573Srgrimes 14284260Sobrien p = *ptr; 1431573Srgrimes 14484260Sobrien if (p[1] == 0) 14584260Sobrien return (-1); 1461573Srgrimes 14784260Sobrien if (*p == '\\') { 14884260Sobrien p++; 14984260Sobrien switch (*p) { 15084260Sobrien case 'a': 15184260Sobrien c = '\007'; /* Bell */ 15284260Sobrien break; 15384260Sobrien case 'b': 15484260Sobrien c = '\010'; /* Backspace */ 15584260Sobrien break; 15684260Sobrien case 't': 15784260Sobrien c = '\011'; /* Horizontal Tab */ 15884260Sobrien break; 15984260Sobrien case 'n': 16084260Sobrien c = '\012'; /* New Line */ 16184260Sobrien break; 16284260Sobrien case 'v': 16384260Sobrien c = '\013'; /* Vertical Tab */ 16484260Sobrien break; 16584260Sobrien case 'f': 16684260Sobrien c = '\014'; /* Form Feed */ 16784260Sobrien break; 16884260Sobrien case 'r': 16984260Sobrien c = '\015'; /* Carriage Return */ 17084260Sobrien break; 17184260Sobrien case 'e': 17284260Sobrien c = '\033'; /* Escape */ 17384260Sobrien break; 17484260Sobrien case '0': 17584260Sobrien case '1': 17684260Sobrien case '2': 17784260Sobrien case '3': 17884260Sobrien case '4': 17984260Sobrien case '5': 18084260Sobrien case '6': 18184260Sobrien case '7': 18284260Sobrien { 18384260Sobrien int cnt, ch; 1841573Srgrimes 18584260Sobrien for (cnt = 0, c = 0; cnt < 3; cnt++) { 18684260Sobrien ch = *p++; 18784260Sobrien if (ch < '0' || ch > '7') { 18884260Sobrien p--; 18984260Sobrien break; 19084260Sobrien } 19184260Sobrien c = (c << 3) | (ch - '0'); 19284260Sobrien } 19384260Sobrien if ((c & 0xffffff00) != 0) 19484260Sobrien return (-1); 19584260Sobrien --p; 1961573Srgrimes break; 1971573Srgrimes } 19884260Sobrien default: 19984260Sobrien c = *p; 20084260Sobrien break; 20184260Sobrien } 202148834Sstefanf } else if (*p == '^') { 20384260Sobrien p++; 20484260Sobrien c = (*p == '?') ? '\177' : (*p & 0237); 20584260Sobrien } else 20684260Sobrien c = *p; 20784260Sobrien *ptr = ++p; 20884260Sobrien return ((unsigned char)c); 2091573Srgrimes} 210148834Sstefanf 2111573Srgrimes/* parse__string(): 2121573Srgrimes * Parse the escapes from in and put the raw string out 2131573Srgrimes */ 2141573Srgrimesprotected char * 21584260Sobrienparse__string(char *out, const char *in) 2161573Srgrimes{ 21784260Sobrien char *rv = out; 21884260Sobrien int n; 2191573Srgrimes 22084260Sobrien for (;;) 22184260Sobrien switch (*in) { 22284260Sobrien case '\0': 22384260Sobrien *out = '\0'; 22484260Sobrien return (rv); 2251573Srgrimes 22684260Sobrien case '\\': 22784260Sobrien case '^': 22884260Sobrien if ((n = parse__escape(&in)) == -1) 22984260Sobrien return (NULL); 23084260Sobrien *out++ = n; 23184260Sobrien break; 23284260Sobrien 233148834Sstefanf case 'M': 234148834Sstefanf if (in[1] == '-' && in[2] != '\0') { 235148834Sstefanf *out++ = '\033'; 236148834Sstefanf in += 2; 237148834Sstefanf break; 238148834Sstefanf } 239148834Sstefanf /*FALLTHROUGH*/ 240148834Sstefanf 24184260Sobrien default: 24284260Sobrien *out++ = *in++; 24384260Sobrien break; 24484260Sobrien } 2451573Srgrimes} 2461573Srgrimes 24784260Sobrien 2481573Srgrimes/* parse_cmd(): 2491573Srgrimes * Return the command number for the command string given 2501573Srgrimes * or -1 if one is not found 2511573Srgrimes */ 2521573Srgrimesprotected int 25384260Sobrienparse_cmd(EditLine *el, const char *cmd) 2541573Srgrimes{ 255277931Semaste el_bindings_t *b = el->el_map.help; 256277931Semaste size_t i; 2571573Srgrimes 258277931Semaste for (i = 0; i < el->el_map.nfunc; i++) 259277931Semaste if (strcmp(b[i].name, cmd) == 0) 260277931Semaste return (b[i].func); 26184260Sobrien return (-1); 2621573Srgrimes} 263