Changeset View
Changeset View
Standalone View
Standalone View
lib/libedit/parse.c
/* $NetBSD: parse.c,v 1.35 2016/02/17 19:47:49 christos Exp $ */ | /* $NetBSD: parse.c,v 1.42 2019/07/23 10:18:52 christos Exp $ */ | ||||
/*- | /*- | ||||
* Copyright (c) 1992, 1993 | * Copyright (c) 1992, 1993 | ||||
* The Regents of the University of California. All rights reserved. | * The Regents of the University of California. All rights reserved. | ||||
* | * | ||||
* This code is derived from software contributed to Berkeley by | * This code is derived from software contributed to Berkeley by | ||||
* Christos Zoulas of Cornell University. | * Christos Zoulas of Cornell University. | ||||
* | * | ||||
Show All 22 Lines | |||||
* SUCH DAMAGE. | * SUCH DAMAGE. | ||||
*/ | */ | ||||
#include "config.h" | #include "config.h" | ||||
#if !defined(lint) && !defined(SCCSID) | #if !defined(lint) && !defined(SCCSID) | ||||
#if 0 | #if 0 | ||||
static char sccsid[] = "@(#)parse.c 8.1 (Berkeley) 6/4/93"; | static char sccsid[] = "@(#)parse.c 8.1 (Berkeley) 6/4/93"; | ||||
#else | #else | ||||
__RCSID("$NetBSD: parse.c,v 1.35 2016/02/17 19:47:49 christos Exp $"); | __RCSID("$NetBSD: parse.c,v 1.42 2019/07/23 10:18:52 christos Exp $"); | ||||
#endif | #endif | ||||
#endif /* not lint && not SCCSID */ | #endif /* not lint && not SCCSID */ | ||||
#include <sys/cdefs.h> | #include <sys/cdefs.h> | ||||
__FBSDID("$FreeBSD$"); | __FBSDID("$FreeBSD$"); | ||||
/* | /* | ||||
* parse.c: parse an editline extended command | * parse.c: parse an editline extended command | ||||
* | * | ||||
* commands are: | * commands are: | ||||
* | * | ||||
* bind | * bind | ||||
* echotc | * echotc | ||||
* edit | * edit | ||||
* gettc | * gettc | ||||
* history | * history | ||||
* settc | * settc | ||||
* setty | * setty | ||||
*/ | */ | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include "el.h" | #include "el.h" | ||||
#include "parse.h" | #include "parse.h" | ||||
private const struct { | static const struct { | ||||
const Char *name; | const wchar_t *name; | ||||
int (*func)(EditLine *, int, const Char **); | int (*func)(EditLine *, int, const wchar_t **); | ||||
} cmds[] = { | } cmds[] = { | ||||
{ STR("bind"), map_bind }, | { L"bind", map_bind }, | ||||
{ STR("echotc"), terminal_echotc }, | { L"echotc", terminal_echotc }, | ||||
{ STR("edit"), el_editmode }, | { L"edit", el_editmode }, | ||||
{ STR("history"), hist_command }, | { L"history", hist_command }, | ||||
{ STR("telltc"), terminal_telltc }, | { L"telltc", terminal_telltc }, | ||||
{ STR("settc"), terminal_settc }, | { L"settc", terminal_settc }, | ||||
{ STR("setty"), tty_stty }, | { L"setty", tty_stty }, | ||||
{ NULL, NULL } | { NULL, NULL } | ||||
}; | }; | ||||
/* parse_line(): | /* parse_line(): | ||||
* Parse a line and dispatch it | * Parse a line and dispatch it | ||||
*/ | */ | ||||
protected int | libedit_private int | ||||
parse_line(EditLine *el, const Char *line) | parse_line(EditLine *el, const wchar_t *line) | ||||
{ | { | ||||
const Char **argv; | const wchar_t **argv; | ||||
int argc; | int argc; | ||||
TYPE(Tokenizer) *tok; | TokenizerW *tok; | ||||
tok = FUN(tok,init)(NULL); | tok = tok_winit(NULL); | ||||
FUN(tok,str)(tok, line, &argc, &argv); | tok_wstr(tok, line, &argc, &argv); | ||||
argc = FUN(el,parse)(el, argc, argv); | argc = el_wparse(el, argc, argv); | ||||
FUN(tok,end)(tok); | tok_wend(tok); | ||||
return argc; | return argc; | ||||
} | } | ||||
/* el_parse(): | /* el_parse(): | ||||
* Command dispatcher | * Command dispatcher | ||||
*/ | */ | ||||
public int | int | ||||
FUN(el,parse)(EditLine *el, int argc, const Char *argv[]) | el_wparse(EditLine *el, int argc, const wchar_t *argv[]) | ||||
{ | { | ||||
const Char *ptr; | const wchar_t *ptr; | ||||
int i; | int i; | ||||
if (argc < 1) | if (argc < 1) | ||||
return -1; | return -1; | ||||
ptr = Strchr(argv[0], ':'); | ptr = wcschr(argv[0], L':'); | ||||
if (ptr != NULL) { | if (ptr != NULL) { | ||||
Char *tprog; | wchar_t *tprog; | ||||
size_t l; | size_t l; | ||||
if (ptr == argv[0]) | if (ptr == argv[0]) | ||||
return 0; | return 0; | ||||
l = (size_t)(ptr - argv[0] - 1); | l = (size_t)(ptr - argv[0]); | ||||
tprog = el_malloc((l + 1) * sizeof(*tprog)); | tprog = el_calloc(l + 1, sizeof(*tprog)); | ||||
if (tprog == NULL) | if (tprog == NULL) | ||||
return 0; | return 0; | ||||
(void) Strncpy(tprog, argv[0], l); | (void) wcsncpy(tprog, argv[0], l); | ||||
tprog[l] = '\0'; | tprog[l] = '\0'; | ||||
ptr++; | ptr++; | ||||
l = (size_t)el_match(el->el_prog, tprog); | l = (size_t)el_match(el->el_prog, tprog); | ||||
el_free(tprog); | el_free(tprog); | ||||
if (!l) | if (!l) | ||||
return 0; | return 0; | ||||
} else | } else | ||||
ptr = argv[0]; | ptr = argv[0]; | ||||
for (i = 0; cmds[i].name != NULL; i++) | for (i = 0; cmds[i].name != NULL; i++) | ||||
if (Strcmp(cmds[i].name, ptr) == 0) { | if (wcscmp(cmds[i].name, ptr) == 0) { | ||||
i = (*cmds[i].func) (el, argc, argv); | i = (*cmds[i].func) (el, argc, argv); | ||||
return -i; | return -i; | ||||
} | } | ||||
return -1; | return -1; | ||||
} | } | ||||
/* parse__escape(): | /* parse__escape(): | ||||
* Parse a string of the form ^<char> \<odigit> \<char> \U+xxxx and return | * Parse a string of the form ^<char> \<odigit> \<char> \U+xxxx and return | ||||
* the appropriate character or -1 if the escape is not valid | * the appropriate character or -1 if the escape is not valid | ||||
*/ | */ | ||||
protected int | libedit_private int | ||||
parse__escape(const Char **ptr) | parse__escape(const wchar_t **ptr) | ||||
{ | { | ||||
const Char *p; | const wchar_t *p; | ||||
wint_t c; | wint_t c; | ||||
p = *ptr; | p = *ptr; | ||||
if (p[1] == 0) | if (p[1] == 0) | ||||
return -1; | return -1; | ||||
if (*p == '\\') { | if (*p == '\\') { | ||||
Show All 18 Lines | case 'f': | ||||
c = '\014'; /* Form Feed */ | c = '\014'; /* Form Feed */ | ||||
break; | break; | ||||
case 'r': | case 'r': | ||||
c = '\015'; /* Carriage Return */ | c = '\015'; /* Carriage Return */ | ||||
break; | break; | ||||
case 'e': | case 'e': | ||||
c = '\033'; /* Escape */ | c = '\033'; /* Escape */ | ||||
break; | break; | ||||
case 'U': /* Unicode \U+xxxx or \U+xxxxx format */ | case 'U': /* Unicode \U+xxxx or \U+xxxxx format */ | ||||
{ | { | ||||
int i; | int i; | ||||
const Char hex[] = STR("0123456789ABCDEF"); | const wchar_t hex[] = L"0123456789ABCDEF"; | ||||
const Char *h; | const wchar_t *h; | ||||
++p; | ++p; | ||||
if (*p++ != '+') | if (*p++ != '+') | ||||
return -1; | return -1; | ||||
c = 0; | c = 0; | ||||
for (i = 0; i < 5; ++i) { | for (i = 0; i < 5; ++i) { | ||||
h = Strchr(hex, *p++); | h = wcschr(hex, *p++); | ||||
if (!h && i < 4) | if (!h && i < 4) | ||||
return -1; | return -1; | ||||
else if (h) | else if (h) | ||||
c = (c << 4) | ((int)(h - hex)); | c = (c << 4) | ((int)(h - hex)); | ||||
else | else | ||||
--p; | --p; | ||||
} | } | ||||
if (c > 0x10FFFF) /* outside valid character range */ | if (c > 0x10FFFF) /* outside valid character range */ | ||||
return -1; | return -1; | ||||
break; | break; | ||||
} | } | ||||
case '0': | case '0': | ||||
case '1': | case '1': | ||||
case '2': | case '2': | ||||
case '3': | case '3': | ||||
case '4': | case '4': | ||||
case '5': | case '5': | ||||
case '6': | case '6': | ||||
case '7': | case '7': | ||||
Show All 24 Lines | if (*p == '\\') { | ||||
c = *p; | c = *p; | ||||
*ptr = ++p; | *ptr = ++p; | ||||
return c; | return c; | ||||
} | } | ||||
/* parse__string(): | /* parse__string(): | ||||
* Parse the escapes from in and put the raw string out | * Parse the escapes from in and put the raw string out | ||||
*/ | */ | ||||
protected Char * | libedit_private wchar_t * | ||||
parse__string(Char *out, const Char *in) | parse__string(wchar_t *out, const wchar_t *in) | ||||
{ | { | ||||
Char *rv = out; | wchar_t *rv = out; | ||||
int n; | int n; | ||||
for (;;) | for (;;) | ||||
switch (*in) { | switch (*in) { | ||||
case '\0': | case '\0': | ||||
*out = '\0'; | *out = '\0'; | ||||
return rv; | return rv; | ||||
case '\\': | case '\\': | ||||
case '^': | case '^': | ||||
if ((n = parse__escape(&in)) == -1) | if ((n = parse__escape(&in)) == -1) | ||||
return NULL; | return NULL; | ||||
*out++ = (Char)n; | *out++ = (wchar_t)n; | ||||
break; | break; | ||||
case 'M': | case 'M': | ||||
if (in[1] == '-' && in[2] != '\0') { | if (in[1] == '-' && in[2] != '\0') { | ||||
*out++ = '\033'; | *out++ = '\033'; | ||||
in += 2; | in += 2; | ||||
break; | break; | ||||
} | } | ||||
/*FALLTHROUGH*/ | /*FALLTHROUGH*/ | ||||
default: | default: | ||||
*out++ = *in++; | *out++ = *in++; | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
/* parse_cmd(): | /* parse_cmd(): | ||||
* Return the command number for the command string given | * Return the command number for the command string given | ||||
* or -1 if one is not found | * or -1 if one is not found | ||||
*/ | */ | ||||
protected int | libedit_private int | ||||
parse_cmd(EditLine *el, const Char *cmd) | parse_cmd(EditLine *el, const wchar_t *cmd) | ||||
{ | { | ||||
el_bindings_t *b = el->el_map.help; | el_bindings_t *b = el->el_map.help; | ||||
size_t i; | size_t i; | ||||
for (i = 0; i < el->el_map.nfunc; i++) | for (i = 0; i < el->el_map.nfunc; i++) | ||||
if (Strcmp(b[i].name, cmd) == 0) | if (wcscmp(b[i].name, cmd) == 0) | ||||
return b[i].func; | return b[i].func; | ||||
return -1; | return -1; | ||||
} | } |