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