1*54224Sbostic /*- 2*54224Sbostic * Copyright (c) 1992 The Regents of the University of California. 3*54224Sbostic * All rights reserved. 4*54224Sbostic * 5*54224Sbostic * This code is derived from software contributed to Berkeley by 6*54224Sbostic * Christos Zoulas of Cornell University. 7*54224Sbostic * 8*54224Sbostic * %sccs.include.redist.c% 9*54224Sbostic */ 10*54224Sbostic 11*54224Sbostic #ifndef lint 12*54224Sbostic static char sccsid[] = "@(#)parse.c 5.1 (Berkeley) 06/22/92"; 13*54224Sbostic #endif /* not lint */ 14*54224Sbostic 15*54224Sbostic /* 16*54224Sbostic * el.parse.c: parse an editline extended command 17*54224Sbostic * 18*54224Sbostic * commands are: 19*54224Sbostic * 20*54224Sbostic * bind 21*54224Sbostic * echotc 22*54224Sbostic * settc 23*54224Sbostic * gettc 24*54224Sbostic */ 25*54224Sbostic #include "sys.h" 26*54224Sbostic #include "el.h" 27*54224Sbostic #include "tokenizer.h" 28*54224Sbostic 29*54224Sbostic private struct { 30*54224Sbostic char *name; 31*54224Sbostic int (*func) __P((EditLine *, int, char **)); 32*54224Sbostic } cmds[] = { 33*54224Sbostic { "bind", map_bind }, 34*54224Sbostic { "echotc", term_echotc }, 35*54224Sbostic { "history", hist_list }, 36*54224Sbostic { "telltc", term_telltc }, 37*54224Sbostic { "settc", term_settc }, 38*54224Sbostic { "setty", tty_stty }, 39*54224Sbostic { NULL, NULL } 40*54224Sbostic }; 41*54224Sbostic 42*54224Sbostic 43*54224Sbostic /* parse_line(): 44*54224Sbostic * Parse a line and dispatch it 45*54224Sbostic */ 46*54224Sbostic protected int 47*54224Sbostic parse_line(el, line) 48*54224Sbostic EditLine *el; 49*54224Sbostic const char *line; 50*54224Sbostic { 51*54224Sbostic char **argv; 52*54224Sbostic int argc; 53*54224Sbostic Tokenizer *tok; 54*54224Sbostic 55*54224Sbostic tok = tok_init(NULL); 56*54224Sbostic tok_line(tok, line, &argc, &argv); 57*54224Sbostic argc = el_parse(el, argc, argv); 58*54224Sbostic tok_end(tok); 59*54224Sbostic return argc; 60*54224Sbostic } 61*54224Sbostic 62*54224Sbostic /* el_parse(): 63*54224Sbostic * Command dispatcher 64*54224Sbostic */ 65*54224Sbostic public int 66*54224Sbostic el_parse(el, argc, argv) 67*54224Sbostic EditLine *el; 68*54224Sbostic int argc; 69*54224Sbostic char *argv[]; 70*54224Sbostic { 71*54224Sbostic char *ptr; 72*54224Sbostic int i; 73*54224Sbostic 74*54224Sbostic for (ptr = argv[0]; *ptr && *ptr != ':'; ptr++) 75*54224Sbostic continue; 76*54224Sbostic 77*54224Sbostic if (*ptr == ':') { 78*54224Sbostic *ptr = '\0'; 79*54224Sbostic if (strcmp(ptr, el->el_prog) != 0) 80*54224Sbostic return 0; 81*54224Sbostic } 82*54224Sbostic else 83*54224Sbostic ptr = argv[0]; 84*54224Sbostic 85*54224Sbostic for (i = 0; cmds[i].name != NULL; i++) 86*54224Sbostic if (strcmp(cmds[i].name, ptr) == 0) { 87*54224Sbostic i = (*cmds[i].func)(el, argc, argv); 88*54224Sbostic return -i; 89*54224Sbostic } 90*54224Sbostic 91*54224Sbostic return -1; 92*54224Sbostic } 93*54224Sbostic 94*54224Sbostic 95*54224Sbostic /* parse__escape(): 96*54224Sbostic * Parse a string of the form ^<char> \<odigit> \<char> and return 97*54224Sbostic * the appropriate character or -1 if the escape is not valid 98*54224Sbostic */ 99*54224Sbostic protected int 100*54224Sbostic parse__escape(ptr) 101*54224Sbostic const char ** const ptr; 102*54224Sbostic { 103*54224Sbostic const char *p; 104*54224Sbostic int c; 105*54224Sbostic 106*54224Sbostic p = *ptr; 107*54224Sbostic 108*54224Sbostic if (p[1] == 0) 109*54224Sbostic return -1; 110*54224Sbostic 111*54224Sbostic if (*p == '\\') { 112*54224Sbostic p++; 113*54224Sbostic switch (*p) { 114*54224Sbostic case 'a': 115*54224Sbostic c = '\007'; /* Bell */ 116*54224Sbostic break; 117*54224Sbostic case 'b': 118*54224Sbostic c = '\010'; /* Backspace */ 119*54224Sbostic break; 120*54224Sbostic case 't': 121*54224Sbostic c = '\011'; /* Horizontal Tab */ 122*54224Sbostic break; 123*54224Sbostic case 'n': 124*54224Sbostic c = '\012'; /* New Line */ 125*54224Sbostic break; 126*54224Sbostic case 'v': 127*54224Sbostic c = '\013'; /* Vertical Tab */ 128*54224Sbostic break; 129*54224Sbostic case 'f': 130*54224Sbostic c = '\014'; /* Form Feed */ 131*54224Sbostic break; 132*54224Sbostic case 'r': 133*54224Sbostic c = '\015'; /* Carriage Return */ 134*54224Sbostic break; 135*54224Sbostic case 'e': 136*54224Sbostic c = '\033'; /* Escape */ 137*54224Sbostic break; 138*54224Sbostic case '0': 139*54224Sbostic case '1': 140*54224Sbostic case '2': 141*54224Sbostic case '3': 142*54224Sbostic case '4': 143*54224Sbostic case '5': 144*54224Sbostic case '6': 145*54224Sbostic case '7': 146*54224Sbostic { 147*54224Sbostic int cnt, ch; 148*54224Sbostic 149*54224Sbostic for (cnt = 0, c = 0; cnt < 3; cnt++) { 150*54224Sbostic ch = *p++; 151*54224Sbostic if (ch < '0' || ch > '7') { 152*54224Sbostic p--; 153*54224Sbostic break; 154*54224Sbostic } 155*54224Sbostic c = (c << 3) | (ch - '0'); 156*54224Sbostic } 157*54224Sbostic if ((c & 0xffffff00) != 0) 158*54224Sbostic return -1; 159*54224Sbostic --p; 160*54224Sbostic } 161*54224Sbostic break; 162*54224Sbostic default: 163*54224Sbostic c = *p; 164*54224Sbostic break; 165*54224Sbostic } 166*54224Sbostic } 167*54224Sbostic else if (*p == '^') { 168*54224Sbostic p++; 169*54224Sbostic c = (*p == '?') ? '\177' : (*p & 0237); 170*54224Sbostic } 171*54224Sbostic else 172*54224Sbostic c = *p; 173*54224Sbostic *ptr = ++p; 174*54224Sbostic return c; 175*54224Sbostic } 176*54224Sbostic 177*54224Sbostic /* parse__string(): 178*54224Sbostic * Parse the escapes from in and put the raw string out 179*54224Sbostic */ 180*54224Sbostic protected char * 181*54224Sbostic parse__string(out, in) 182*54224Sbostic char *out; 183*54224Sbostic const char *in; 184*54224Sbostic { 185*54224Sbostic char *rv = out; 186*54224Sbostic int n; 187*54224Sbostic for (;;) 188*54224Sbostic switch (*in) { 189*54224Sbostic case '\0': 190*54224Sbostic *out = '\0'; 191*54224Sbostic return rv; 192*54224Sbostic 193*54224Sbostic case '\\': 194*54224Sbostic case '^': 195*54224Sbostic if ((n = parse__escape(&in)) == -1) 196*54224Sbostic return NULL; 197*54224Sbostic *out++ = n; 198*54224Sbostic break; 199*54224Sbostic 200*54224Sbostic default: 201*54224Sbostic *out++ = *in++; 202*54224Sbostic break; 203*54224Sbostic } 204*54224Sbostic } 205*54224Sbostic 206*54224Sbostic /* parse_cmd(): 207*54224Sbostic * Return the command number for the command string given 208*54224Sbostic * or -1 if one is not found 209*54224Sbostic */ 210*54224Sbostic protected int 211*54224Sbostic parse_cmd(el, cmd) 212*54224Sbostic EditLine *el; 213*54224Sbostic const char *cmd; 214*54224Sbostic { 215*54224Sbostic el_bindings_t *b; 216*54224Sbostic 217*54224Sbostic for (b = el->el_map.help; b->name != NULL; b++) 218*54224Sbostic if (strcmp(b->name, cmd) == 0) 219*54224Sbostic return b->func; 220*54224Sbostic return -1; 221*54224Sbostic } 222