1 /* $OpenBSD: parse.c,v 1.6 2003/06/02 20:18:40 millert Exp $ */ 2 /* $NetBSD: parse.c,v 1.5 1997/01/11 09:57:08 lukem 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 #if !defined(lint) && !defined(SCCSID) 37 #if 0 38 static char sccsid[] = "@(#)parse.c 8.1 (Berkeley) 6/4/93"; 39 #else 40 static const char rcsid[] = "$OpenBSD: parse.c,v 1.6 2003/06/02 20:18:40 millert 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 * gettc 52 * history 53 * settc 54 * setty 55 */ 56 #include "sys.h" 57 #include "el.h" 58 #include "tokenizer.h" 59 60 private struct { 61 char *name; 62 int (*func)(EditLine *, int, char **); 63 } cmds[] = { 64 { "bind", map_bind }, 65 { "echotc", term_echotc }, 66 { "history", hist_list }, 67 { "telltc", term_telltc }, 68 { "settc", term_settc }, 69 { "setty", tty_stty }, 70 { NULL, NULL } 71 }; 72 73 74 /* parse_line(): 75 * Parse a line and dispatch it 76 */ 77 protected int 78 parse_line(el, line) 79 EditLine *el; 80 const char *line; 81 { 82 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 /* el_parse(): 94 * Command dispatcher 95 */ 96 public int 97 el_parse(el, argc, argv) 98 EditLine *el; 99 int argc; 100 char *argv[]; 101 { 102 char *ptr; 103 int i; 104 105 if (argc < 1) 106 return -1; 107 ptr = strchr(argv[0], ':'); 108 if (ptr != NULL) { 109 *ptr++ = '\0'; 110 if (! el_match(el->el_prog, argv[0])) 111 return 0; 112 } 113 else 114 ptr = argv[0]; 115 116 for (i = 0; cmds[i].name != NULL; i++) 117 if (strcmp(cmds[i].name, ptr) == 0) { 118 i = (*cmds[i].func)(el, argc, argv); 119 return -i; 120 } 121 122 return -1; 123 } 124 125 126 /* parse__escape(): 127 * Parse a string of the form ^<char> \<odigit> \<char> and return 128 * the appropriate character or -1 if the escape is not valid 129 */ 130 protected int 131 parse__escape(ptr) 132 const char ** const ptr; 133 { 134 const char *p; 135 int c; 136 137 p = *ptr; 138 139 if (p[1] == 0) 140 return -1; 141 142 if (*p == '\\') { 143 p++; 144 switch (*p) { 145 case 'a': 146 c = '\007'; /* Bell */ 147 break; 148 case 'b': 149 c = '\010'; /* Backspace */ 150 break; 151 case 't': 152 c = '\011'; /* Horizontal Tab */ 153 break; 154 case 'n': 155 c = '\012'; /* New Line */ 156 break; 157 case 'v': 158 c = '\013'; /* Vertical Tab */ 159 break; 160 case 'f': 161 c = '\014'; /* Form Feed */ 162 break; 163 case 'r': 164 c = '\015'; /* Carriage Return */ 165 break; 166 case 'e': 167 c = '\033'; /* Escape */ 168 break; 169 case '0': 170 case '1': 171 case '2': 172 case '3': 173 case '4': 174 case '5': 175 case '6': 176 case '7': 177 { 178 int cnt, ch; 179 180 for (cnt = 0, c = 0; cnt < 3; cnt++) { 181 ch = *p++; 182 if (ch < '0' || ch > '7') { 183 p--; 184 break; 185 } 186 c = (c << 3) | (ch - '0'); 187 } 188 if ((c & 0xffffff00) != 0) 189 return -1; 190 --p; 191 } 192 break; 193 default: 194 c = *p; 195 break; 196 } 197 } 198 else if (*p == '^' && isalpha((unsigned char) p[1])) { 199 p++; 200 c = (*p == '?') ? '\177' : (*p & 0237); 201 } 202 else 203 c = *p; 204 *ptr = ++p; 205 return c; 206 } 207 208 /* parse__string(): 209 * Parse the escapes from in and put the raw string out 210 */ 211 protected char * 212 parse__string(out, in) 213 char *out; 214 const char *in; 215 { 216 char *rv = out; 217 int n; 218 for (;;) 219 switch (*in) { 220 case '\0': 221 *out = '\0'; 222 return rv; 223 224 case '\\': 225 case '^': 226 if ((n = parse__escape(&in)) == -1) 227 return NULL; 228 *out++ = n; 229 break; 230 231 default: 232 *out++ = *in++; 233 break; 234 } 235 } 236 237 /* parse_cmd(): 238 * Return the command number for the command string given 239 * or -1 if one is not found 240 */ 241 protected int 242 parse_cmd(el, cmd) 243 EditLine *el; 244 const char *cmd; 245 { 246 el_bindings_t *b; 247 248 for (b = el->el_map.help; b->name != NULL; b++) 249 if (strcmp(b->name, cmd) == 0) 250 return b->func; 251 return -1; 252 } 253