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