hush: make getch/peek functions directly called
Indirect calls are more difficult to predict. Unfortunately, on x64 direct call is 5 bytes while indirect "call (reg+ofs)" is 3 bytes: function old new delta i_getch - 82 +82 i_peek - 63 +63 parse_stream 2531 2579 +48 parse_dollar 771 797 +26 parse_redirect 296 321 +25 add_till_closing_bracket 408 420 +12 encode_string 256 265 +9 i_peek_and_eat_bkslash_nl 93 99 +6 add_till_backquote 110 114 +4 parse_and_run_stream 139 141 +2 expand_vars_to_list 1143 1144 +1 static_peek 6 - -6 setup_string_in_str 39 18 -21 setup_file_in_str 40 19 -21 static_get 27 - -27 file_peek 52 - -52 file_get 65 - -65 ------------------------------------------------------------------------------ (add/remove: 2/4 grow/shrink: 9/2 up/down: 278/-192) Total: 86 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
00a06b9715
commit
87e039d016
51
shell/hush.c
51
shell/hush.c
@ -469,11 +469,7 @@ typedef struct in_str {
|
|||||||
int peek_buf[2];
|
int peek_buf[2];
|
||||||
int last_char;
|
int last_char;
|
||||||
FILE *file;
|
FILE *file;
|
||||||
int (*get) (struct in_str *) FAST_FUNC;
|
|
||||||
int (*peek) (struct in_str *) FAST_FUNC;
|
|
||||||
} in_str;
|
} in_str;
|
||||||
#define i_getch(input) ((input)->get(input))
|
|
||||||
#define i_peek(input) ((input)->peek(input))
|
|
||||||
|
|
||||||
/* The descrip member of this structure is only used to make
|
/* The descrip member of this structure is only used to make
|
||||||
* debugging output pretty */
|
* debugging output pretty */
|
||||||
@ -2259,10 +2255,23 @@ static inline int fgetc_interactive(struct in_str *i)
|
|||||||
}
|
}
|
||||||
#endif /* INTERACTIVE */
|
#endif /* INTERACTIVE */
|
||||||
|
|
||||||
static int FAST_FUNC file_get(struct in_str *i)
|
static int i_getch(struct in_str *i)
|
||||||
{
|
{
|
||||||
int ch;
|
int ch;
|
||||||
|
|
||||||
|
if (!i->file) {
|
||||||
|
/* string-based in_str */
|
||||||
|
ch = (unsigned char)*i->p;
|
||||||
|
if (ch != '\0') {
|
||||||
|
i->p++;
|
||||||
|
i->last_char = ch;
|
||||||
|
return ch;
|
||||||
|
}
|
||||||
|
return EOF;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FILE-based in_str */
|
||||||
|
|
||||||
#if ENABLE_FEATURE_EDITING
|
#if ENABLE_FEATURE_EDITING
|
||||||
/* This can be stdin, check line editing char[] buffer */
|
/* This can be stdin, check line editing char[] buffer */
|
||||||
if (i->p && *i->p != '\0') {
|
if (i->p && *i->p != '\0') {
|
||||||
@ -2288,10 +2297,18 @@ static int FAST_FUNC file_get(struct in_str *i)
|
|||||||
return ch;
|
return ch;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int FAST_FUNC file_peek(struct in_str *i)
|
static int i_peek(struct in_str *i)
|
||||||
{
|
{
|
||||||
int ch;
|
int ch;
|
||||||
|
|
||||||
|
if (!i->file) {
|
||||||
|
/* string-based in_str */
|
||||||
|
/* Doesn't report EOF on NUL. None of the callers care. */
|
||||||
|
return (unsigned char)*i->p;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FILE-based in_str */
|
||||||
|
|
||||||
#if ENABLE_FEATURE_EDITING && ENABLE_HUSH_INTERACTIVE
|
#if ENABLE_FEATURE_EDITING && ENABLE_HUSH_INTERACTIVE
|
||||||
/* This can be stdin, check line editing char[] buffer */
|
/* This can be stdin, check line editing char[] buffer */
|
||||||
if (i->p && *i->p != '\0')
|
if (i->p && *i->p != '\0')
|
||||||
@ -2318,23 +2335,6 @@ static int FAST_FUNC file_peek(struct in_str *i)
|
|||||||
return ch;
|
return ch;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int FAST_FUNC static_get(struct in_str *i)
|
|
||||||
{
|
|
||||||
int ch = (unsigned char)*i->p;
|
|
||||||
if (ch != '\0') {
|
|
||||||
i->p++;
|
|
||||||
i->last_char = ch;
|
|
||||||
return ch;
|
|
||||||
}
|
|
||||||
return EOF;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int FAST_FUNC static_peek(struct in_str *i)
|
|
||||||
{
|
|
||||||
/* Doesn't report EOF on NUL. None of the callers care. */
|
|
||||||
return (unsigned char)*i->p;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Only ever called if i_peek() was called, and did not return EOF.
|
/* Only ever called if i_peek() was called, and did not return EOF.
|
||||||
* IOW: we know the previous peek saw an ordinary char, not EOF, not NUL,
|
* IOW: we know the previous peek saw an ordinary char, not EOF, not NUL,
|
||||||
* not end-of-line. Therefore we never need to read a new editing line here.
|
* not end-of-line. Therefore we never need to read a new editing line here.
|
||||||
@ -2370,8 +2370,6 @@ static int i_peek2(struct in_str *i)
|
|||||||
static void setup_file_in_str(struct in_str *i, FILE *f)
|
static void setup_file_in_str(struct in_str *i, FILE *f)
|
||||||
{
|
{
|
||||||
memset(i, 0, sizeof(*i));
|
memset(i, 0, sizeof(*i));
|
||||||
i->get = file_get;
|
|
||||||
i->peek = file_peek;
|
|
||||||
/* i->promptmode = 0; - PS1 (memset did it) */
|
/* i->promptmode = 0; - PS1 (memset did it) */
|
||||||
i->file = f;
|
i->file = f;
|
||||||
/* i->p = NULL; */
|
/* i->p = NULL; */
|
||||||
@ -2380,9 +2378,8 @@ static void setup_file_in_str(struct in_str *i, FILE *f)
|
|||||||
static void setup_string_in_str(struct in_str *i, const char *s)
|
static void setup_string_in_str(struct in_str *i, const char *s)
|
||||||
{
|
{
|
||||||
memset(i, 0, sizeof(*i));
|
memset(i, 0, sizeof(*i));
|
||||||
i->get = static_get;
|
|
||||||
i->peek = static_peek;
|
|
||||||
/* i->promptmode = 0; - PS1 (memset did it) */
|
/* i->promptmode = 0; - PS1 (memset did it) */
|
||||||
|
/*i->file = NULL */;
|
||||||
i->p = s;
|
i->p = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user