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