1*32fe07f8SJohn Marino /* $NetBSD: parse.c,v 1.26 2011/08/16 16:25:15 christos Exp $ */ 2*32fe07f8SJohn Marino 3*32fe07f8SJohn Marino /*- 4*32fe07f8SJohn Marino * Copyright (c) 1992, 1993 5*32fe07f8SJohn Marino * The Regents of the University of California. All rights reserved. 6*32fe07f8SJohn Marino * 7*32fe07f8SJohn Marino * This code is derived from software contributed to Berkeley by 8*32fe07f8SJohn Marino * Christos Zoulas of Cornell University. 9*32fe07f8SJohn Marino * 10*32fe07f8SJohn Marino * Redistribution and use in source and binary forms, with or without 11*32fe07f8SJohn Marino * modification, are permitted provided that the following conditions 12*32fe07f8SJohn Marino * are met: 13*32fe07f8SJohn Marino * 1. Redistributions of source code must retain the above copyright 14*32fe07f8SJohn Marino * notice, this list of conditions and the following disclaimer. 15*32fe07f8SJohn Marino * 2. Redistributions in binary form must reproduce the above copyright 16*32fe07f8SJohn Marino * notice, this list of conditions and the following disclaimer in the 17*32fe07f8SJohn Marino * documentation and/or other materials provided with the distribution. 18*32fe07f8SJohn Marino * 3. Neither the name of the University nor the names of its contributors 19*32fe07f8SJohn Marino * may be used to endorse or promote products derived from this software 20*32fe07f8SJohn Marino * without specific prior written permission. 21*32fe07f8SJohn Marino * 22*32fe07f8SJohn Marino * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23*32fe07f8SJohn Marino * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24*32fe07f8SJohn Marino * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25*32fe07f8SJohn Marino * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26*32fe07f8SJohn Marino * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27*32fe07f8SJohn Marino * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28*32fe07f8SJohn Marino * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29*32fe07f8SJohn Marino * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30*32fe07f8SJohn Marino * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31*32fe07f8SJohn Marino * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32*32fe07f8SJohn Marino * SUCH DAMAGE. 33*32fe07f8SJohn Marino */ 34*32fe07f8SJohn Marino 35*32fe07f8SJohn Marino #include "config.h" 36*32fe07f8SJohn Marino #if !defined(lint) && !defined(SCCSID) 37*32fe07f8SJohn Marino #if 0 38*32fe07f8SJohn Marino static char sccsid[] = "@(#)parse.c 8.1 (Berkeley) 6/4/93"; 39*32fe07f8SJohn Marino #else 40*32fe07f8SJohn Marino __RCSID("$NetBSD: parse.c,v 1.26 2011/08/16 16:25:15 christos Exp $"); 41*32fe07f8SJohn Marino #endif 42*32fe07f8SJohn Marino #endif /* not lint && not SCCSID */ 43*32fe07f8SJohn Marino 44*32fe07f8SJohn Marino /* 45*32fe07f8SJohn Marino * parse.c: parse an editline extended command 46*32fe07f8SJohn Marino * 47*32fe07f8SJohn Marino * commands are: 48*32fe07f8SJohn Marino * 49*32fe07f8SJohn Marino * bind 50*32fe07f8SJohn Marino * echotc 51*32fe07f8SJohn Marino * edit 52*32fe07f8SJohn Marino * gettc 53*32fe07f8SJohn Marino * history 54*32fe07f8SJohn Marino * settc 55*32fe07f8SJohn Marino * setty 56*32fe07f8SJohn Marino */ 57*32fe07f8SJohn Marino #include "el.h" 58*32fe07f8SJohn Marino #include <stdlib.h> 59*32fe07f8SJohn Marino 60*32fe07f8SJohn Marino private const struct { 61*32fe07f8SJohn Marino const Char *name; 62*32fe07f8SJohn Marino int (*func)(EditLine *, int, const Char **); 63*32fe07f8SJohn Marino } cmds[] = { 64*32fe07f8SJohn Marino { STR("bind"), map_bind }, 65*32fe07f8SJohn Marino { STR("echotc"), terminal_echotc }, 66*32fe07f8SJohn Marino { STR("edit"), el_editmode }, 67*32fe07f8SJohn Marino { STR("history"), hist_command }, 68*32fe07f8SJohn Marino { STR("telltc"), terminal_telltc }, 69*32fe07f8SJohn Marino { STR("settc"), terminal_settc }, 70*32fe07f8SJohn Marino { STR("setty"), tty_stty }, 71*32fe07f8SJohn Marino { NULL, NULL } 72*32fe07f8SJohn Marino }; 73*32fe07f8SJohn Marino 74*32fe07f8SJohn Marino 75*32fe07f8SJohn Marino /* parse_line(): 76*32fe07f8SJohn Marino * Parse a line and dispatch it 77*32fe07f8SJohn Marino */ 78*32fe07f8SJohn Marino protected int 79*32fe07f8SJohn Marino parse_line(EditLine *el, const Char *line) 80*32fe07f8SJohn Marino { 81*32fe07f8SJohn Marino const Char **argv; 82*32fe07f8SJohn Marino int argc; 83*32fe07f8SJohn Marino TYPE(Tokenizer) *tok; 84*32fe07f8SJohn Marino 85*32fe07f8SJohn Marino tok = FUN(tok,init)(NULL); 86*32fe07f8SJohn Marino FUN(tok,str)(tok, line, &argc, &argv); 87*32fe07f8SJohn Marino argc = FUN(el,parse)(el, argc, argv); 88*32fe07f8SJohn Marino FUN(tok,end)(tok); 89*32fe07f8SJohn Marino return argc; 90*32fe07f8SJohn Marino } 91*32fe07f8SJohn Marino 92*32fe07f8SJohn Marino 93*32fe07f8SJohn Marino /* el_parse(): 94*32fe07f8SJohn Marino * Command dispatcher 95*32fe07f8SJohn Marino */ 96*32fe07f8SJohn Marino public int 97*32fe07f8SJohn Marino FUN(el,parse)(EditLine *el, int argc, const Char *argv[]) 98*32fe07f8SJohn Marino { 99*32fe07f8SJohn Marino const Char *ptr; 100*32fe07f8SJohn Marino int i; 101*32fe07f8SJohn Marino 102*32fe07f8SJohn Marino if (argc < 1) 103*32fe07f8SJohn Marino return -1; 104*32fe07f8SJohn Marino ptr = Strchr(argv[0], ':'); 105*32fe07f8SJohn Marino if (ptr != NULL) { 106*32fe07f8SJohn Marino Char *tprog; 107*32fe07f8SJohn Marino size_t l; 108*32fe07f8SJohn Marino 109*32fe07f8SJohn Marino if (ptr == argv[0]) 110*32fe07f8SJohn Marino return 0; 111*32fe07f8SJohn Marino l = (size_t)(ptr - argv[0] - 1); 112*32fe07f8SJohn Marino tprog = el_malloc((l + 1) * sizeof(*tprog)); 113*32fe07f8SJohn Marino if (tprog == NULL) 114*32fe07f8SJohn Marino return 0; 115*32fe07f8SJohn Marino (void) Strncpy(tprog, argv[0], l); 116*32fe07f8SJohn Marino tprog[l] = '\0'; 117*32fe07f8SJohn Marino ptr++; 118*32fe07f8SJohn Marino l = (size_t)el_match(el->el_prog, tprog); 119*32fe07f8SJohn Marino el_free(tprog); 120*32fe07f8SJohn Marino if (!l) 121*32fe07f8SJohn Marino return 0; 122*32fe07f8SJohn Marino } else 123*32fe07f8SJohn Marino ptr = argv[0]; 124*32fe07f8SJohn Marino 125*32fe07f8SJohn Marino for (i = 0; cmds[i].name != NULL; i++) 126*32fe07f8SJohn Marino if (Strcmp(cmds[i].name, ptr) == 0) { 127*32fe07f8SJohn Marino i = (*cmds[i].func) (el, argc, argv); 128*32fe07f8SJohn Marino return -i; 129*32fe07f8SJohn Marino } 130*32fe07f8SJohn Marino return -1; 131*32fe07f8SJohn Marino } 132*32fe07f8SJohn Marino 133*32fe07f8SJohn Marino 134*32fe07f8SJohn Marino /* parse__escape(): 135*32fe07f8SJohn Marino * Parse a string of the form ^<char> \<odigit> \<char> \U+xxxx and return 136*32fe07f8SJohn Marino * the appropriate character or -1 if the escape is not valid 137*32fe07f8SJohn Marino */ 138*32fe07f8SJohn Marino protected int 139*32fe07f8SJohn Marino parse__escape(const Char **ptr) 140*32fe07f8SJohn Marino { 141*32fe07f8SJohn Marino const Char *p; 142*32fe07f8SJohn Marino Int c; 143*32fe07f8SJohn Marino 144*32fe07f8SJohn Marino p = *ptr; 145*32fe07f8SJohn Marino 146*32fe07f8SJohn Marino if (p[1] == 0) 147*32fe07f8SJohn Marino return -1; 148*32fe07f8SJohn Marino 149*32fe07f8SJohn Marino if (*p == '\\') { 150*32fe07f8SJohn Marino p++; 151*32fe07f8SJohn Marino switch (*p) { 152*32fe07f8SJohn Marino case 'a': 153*32fe07f8SJohn Marino c = '\007'; /* Bell */ 154*32fe07f8SJohn Marino break; 155*32fe07f8SJohn Marino case 'b': 156*32fe07f8SJohn Marino c = '\010'; /* Backspace */ 157*32fe07f8SJohn Marino break; 158*32fe07f8SJohn Marino case 't': 159*32fe07f8SJohn Marino c = '\011'; /* Horizontal Tab */ 160*32fe07f8SJohn Marino break; 161*32fe07f8SJohn Marino case 'n': 162*32fe07f8SJohn Marino c = '\012'; /* New Line */ 163*32fe07f8SJohn Marino break; 164*32fe07f8SJohn Marino case 'v': 165*32fe07f8SJohn Marino c = '\013'; /* Vertical Tab */ 166*32fe07f8SJohn Marino break; 167*32fe07f8SJohn Marino case 'f': 168*32fe07f8SJohn Marino c = '\014'; /* Form Feed */ 169*32fe07f8SJohn Marino break; 170*32fe07f8SJohn Marino case 'r': 171*32fe07f8SJohn Marino c = '\015'; /* Carriage Return */ 172*32fe07f8SJohn Marino break; 173*32fe07f8SJohn Marino case 'e': 174*32fe07f8SJohn Marino c = '\033'; /* Escape */ 175*32fe07f8SJohn Marino break; 176*32fe07f8SJohn Marino case 'U': /* Unicode \U+xxxx or \U+xxxxx format */ 177*32fe07f8SJohn Marino { 178*32fe07f8SJohn Marino int i; 179*32fe07f8SJohn Marino const Char hex[] = STR("0123456789ABCDEF"); 180*32fe07f8SJohn Marino const Char *h; 181*32fe07f8SJohn Marino ++p; 182*32fe07f8SJohn Marino if (*p++ != '+') 183*32fe07f8SJohn Marino return -1; 184*32fe07f8SJohn Marino c = 0; 185*32fe07f8SJohn Marino for (i = 0; i < 5; ++i) { 186*32fe07f8SJohn Marino h = Strchr(hex, *p++); 187*32fe07f8SJohn Marino if (!h && i < 4) 188*32fe07f8SJohn Marino return -1; 189*32fe07f8SJohn Marino else if (h) 190*32fe07f8SJohn Marino c = (c << 4) | ((int)(h - hex)); 191*32fe07f8SJohn Marino else 192*32fe07f8SJohn Marino --p; 193*32fe07f8SJohn Marino } 194*32fe07f8SJohn Marino if (c > 0x10FFFF) /* outside valid character range */ 195*32fe07f8SJohn Marino return -1; 196*32fe07f8SJohn Marino break; 197*32fe07f8SJohn Marino } 198*32fe07f8SJohn Marino case '0': 199*32fe07f8SJohn Marino case '1': 200*32fe07f8SJohn Marino case '2': 201*32fe07f8SJohn Marino case '3': 202*32fe07f8SJohn Marino case '4': 203*32fe07f8SJohn Marino case '5': 204*32fe07f8SJohn Marino case '6': 205*32fe07f8SJohn Marino case '7': 206*32fe07f8SJohn Marino { 207*32fe07f8SJohn Marino int cnt, ch; 208*32fe07f8SJohn Marino 209*32fe07f8SJohn Marino for (cnt = 0, c = 0; cnt < 3; cnt++) { 210*32fe07f8SJohn Marino ch = *p++; 211*32fe07f8SJohn Marino if (ch < '0' || ch > '7') { 212*32fe07f8SJohn Marino p--; 213*32fe07f8SJohn Marino break; 214*32fe07f8SJohn Marino } 215*32fe07f8SJohn Marino c = (c << 3) | (ch - '0'); 216*32fe07f8SJohn Marino } 217*32fe07f8SJohn Marino if ((c & (wint_t)0xffffff00) != (wint_t)0) 218*32fe07f8SJohn Marino return -1; 219*32fe07f8SJohn Marino --p; 220*32fe07f8SJohn Marino break; 221*32fe07f8SJohn Marino } 222*32fe07f8SJohn Marino default: 223*32fe07f8SJohn Marino c = *p; 224*32fe07f8SJohn Marino break; 225*32fe07f8SJohn Marino } 226*32fe07f8SJohn Marino } else if (*p == '^') { 227*32fe07f8SJohn Marino p++; 228*32fe07f8SJohn Marino c = (*p == '?') ? '\177' : (*p & 0237); 229*32fe07f8SJohn Marino } else 230*32fe07f8SJohn Marino c = *p; 231*32fe07f8SJohn Marino *ptr = ++p; 232*32fe07f8SJohn Marino return c; 233*32fe07f8SJohn Marino } 234*32fe07f8SJohn Marino 235*32fe07f8SJohn Marino /* parse__string(): 236*32fe07f8SJohn Marino * Parse the escapes from in and put the raw string out 237*32fe07f8SJohn Marino */ 238*32fe07f8SJohn Marino protected Char * 239*32fe07f8SJohn Marino parse__string(Char *out, const Char *in) 240*32fe07f8SJohn Marino { 241*32fe07f8SJohn Marino Char *rv = out; 242*32fe07f8SJohn Marino int n; 243*32fe07f8SJohn Marino 244*32fe07f8SJohn Marino for (;;) 245*32fe07f8SJohn Marino switch (*in) { 246*32fe07f8SJohn Marino case '\0': 247*32fe07f8SJohn Marino *out = '\0'; 248*32fe07f8SJohn Marino return rv; 249*32fe07f8SJohn Marino 250*32fe07f8SJohn Marino case '\\': 251*32fe07f8SJohn Marino case '^': 252*32fe07f8SJohn Marino if ((n = parse__escape(&in)) == -1) 253*32fe07f8SJohn Marino return NULL; 254*32fe07f8SJohn Marino *out++ = n; 255*32fe07f8SJohn Marino break; 256*32fe07f8SJohn Marino 257*32fe07f8SJohn Marino case 'M': 258*32fe07f8SJohn Marino if (in[1] == '-' && in[2] != '\0') { 259*32fe07f8SJohn Marino *out++ = '\033'; 260*32fe07f8SJohn Marino in += 2; 261*32fe07f8SJohn Marino break; 262*32fe07f8SJohn Marino } 263*32fe07f8SJohn Marino /*FALLTHROUGH*/ 264*32fe07f8SJohn Marino 265*32fe07f8SJohn Marino default: 266*32fe07f8SJohn Marino *out++ = *in++; 267*32fe07f8SJohn Marino break; 268*32fe07f8SJohn Marino } 269*32fe07f8SJohn Marino } 270*32fe07f8SJohn Marino 271*32fe07f8SJohn Marino 272*32fe07f8SJohn Marino /* parse_cmd(): 273*32fe07f8SJohn Marino * Return the command number for the command string given 274*32fe07f8SJohn Marino * or -1 if one is not found 275*32fe07f8SJohn Marino */ 276*32fe07f8SJohn Marino protected int 277*32fe07f8SJohn Marino parse_cmd(EditLine *el, const Char *cmd) 278*32fe07f8SJohn Marino { 279*32fe07f8SJohn Marino el_bindings_t *b; 280*32fe07f8SJohn Marino 281*32fe07f8SJohn Marino for (b = el->el_map.help; b->name != NULL; b++) 282*32fe07f8SJohn Marino if (Strcmp(b->name, cmd) == 0) 283*32fe07f8SJohn Marino return b->func; 284*32fe07f8SJohn Marino return -1; 285*32fe07f8SJohn Marino } 286