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