diff options
author | Denys Vlasenko | 2016-11-08 22:35:05 +0100 |
---|---|---|
committer | Denys Vlasenko | 2016-11-08 22:35:05 +0100 |
commit | 87e039d0160be16a9a242f74af2e90cdb9f97e12 (patch) | |
tree | 6d426cbcb065ba5dc1a7e10717d67a1e74987d88 | |
parent | 00a06b971531031103c25d650e2078c801afbe39 (diff) | |
download | busybox-87e039d0160be16a9a242f74af2e90cdb9f97e12.zip busybox-87e039d0160be16a9a242f74af2e90cdb9f97e12.tar.gz |
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>
-rw-r--r-- | shell/hush.c | 51 |
1 files changed, 24 insertions, 27 deletions
diff --git a/shell/hush.c b/shell/hush.c index 57252a1..2f07f4a 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -469,11 +469,7 @@ typedef struct in_str { int peek_buf[2]; int last_char; FILE *file; - int (*get) (struct in_str *) FAST_FUNC; - int (*peek) (struct in_str *) FAST_FUNC; } 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 * debugging output pretty */ @@ -2259,10 +2255,23 @@ static inline int fgetc_interactive(struct in_str *i) } #endif /* INTERACTIVE */ -static int FAST_FUNC file_get(struct in_str *i) +static int i_getch(struct in_str *i) { 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 /* This can be stdin, check line editing char[] buffer */ if (i->p && *i->p != '\0') { @@ -2288,10 +2297,18 @@ static int FAST_FUNC file_get(struct in_str *i) return ch; } -static int FAST_FUNC file_peek(struct in_str *i) +static int i_peek(struct in_str *i) { 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 /* This can be stdin, check line editing char[] buffer */ if (i->p && *i->p != '\0') @@ -2318,23 +2335,6 @@ static int FAST_FUNC file_peek(struct in_str *i) 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. * 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. @@ -2370,8 +2370,6 @@ static int i_peek2(struct in_str *i) static void setup_file_in_str(struct in_str *i, FILE *f) { memset(i, 0, sizeof(*i)); - i->get = file_get; - i->peek = file_peek; /* i->promptmode = 0; - PS1 (memset did it) */ i->file = f; /* 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) { memset(i, 0, sizeof(*i)); - i->get = static_get; - i->peek = static_peek; /* i->promptmode = 0; - PS1 (memset did it) */ + /*i->file = NULL */; i->p = s; } |