less: stop using data/bss. Code got smaller too. # size busybox_old busybox_unstripped text data bss dec hex filename 700719 2896 17880 721495 b0257 busybox_old 700547 2832 17432 720811 affab busybox_unstripped # size */*/less.o text data bss dec
No binary (build failed)
—
(log yok)
| @@ -72,27 +72,6 @@ enum { | |
| TILDES = 1, | |
| }; | |
| - | static unsigned max_displayed_line; |
| - | static unsigned width; |
| - | static const char *empty_line_marker = "~"; |
| - | |
| - | static char *filename; |
| - | static char **files; |
| - | static unsigned num_files = 1; |
| - | static unsigned current_file = 1; |
| - | static const char **buffer; |
| - | static const char **flines; |
| - | static int cur_fline; /* signed */ |
| - | static unsigned max_fline; |
| - | static unsigned max_lineno; /* this one tracks linewrap */ |
| - | |
| - | static ssize_t eof_error = 1; /* eof if 0, error if < 0 */ |
| - | static char terminated = 1; |
| - | static size_t readpos; |
| - | static size_t readeof; |
| - | /* last position in last line, taking into account tabs */ |
| - | static size_t linepos; |
| - | |
| /* Command line options */ | |
| enum { | |
| FLAG_E = 1, | |
| @@ -104,25 +83,79 @@ enum { | |
| LESS_STATE_MATCH_BACKWARDS = 1 << 15, | |
| }; | |
| - | #if ENABLE_FEATURE_LESS_MARKS |
| - | static unsigned mark_lines[15][2]; |
| - | static unsigned num_marks; |
| + | #if !ENABLE_FEATURE_LESS_REGEXP |
| + | enum { pattern_valid = 0 }; |
| #endif | |
| + | struct globals { |
| + | int cur_fline; /* signed */ |
| + | int kbd_fd; /* fd to get input from */ |
| + | /* last position in last line, taking into account tabs */ |
| + | size_t linepos; |
| + | unsigned max_displayed_line; |
| + | unsigned max_fline; |
| + | unsigned max_lineno; /* this one tracks linewrap */ |
| + | unsigned width; |
| + | ssize_t eof_error; /* eof if 0, error if < 0 */ |
| + | size_t readpos; |
| + | size_t readeof; |
| + | const char **buffer; |
| + | const char **flines; |
| + | const char *empty_line_marker; |
| + | unsigned num_files; |
| + | unsigned current_file; |
| + | char *filename; |
| + | char **files; |
| + | #if ENABLE_FEATURE_LESS_MARKS |
| + | unsigned num_marks; |
| + | unsigned mark_lines[15][2]; |
| + | #endif |
| #if ENABLE_FEATURE_LESS_REGEXP | |
| - | static unsigned *match_lines; |
| - | static int match_pos; /* signed! */ |
| - | static unsigned num_matches; |
| - | static regex_t pattern; |
| - | static unsigned pattern_valid; |
| - | #else |
| - | enum { pattern_valid = 0 }; |
| + | unsigned *match_lines; |
| + | int match_pos; /* signed! */ |
| + | unsigned num_matches; |
| + | regex_t pattern; |
| + | smallint pattern_valid; |
| #endif | |
| - | |
| - | static struct termios term_orig, term_vi; |
| - | |
| - | /* File pointer to get input from */ |
| - | static int kbd_fd; |
| + | smallint terminated; |
| + | struct termios term_orig, term_less; |
| + | }; |
| + | #define G (*ptr_to_globals) |
| + | #define cur_fline (G.cur_fline ) |
| + | #define kbd_fd (G.kbd_fd ) |
| + | #define linepos (G.linepos ) |
| + | #define max_displayed_line (G.max_displayed_line) |
| + | #define max_fline (G.max_fline ) |
| + | #define max_lineno (G.max_lineno ) |
| + | #define width (G.width ) |
| + | #define eof_error (G.eof_error ) |
| + | #define readpos (G.readpos ) |
| + | #define readeof (G.readeof ) |
| + | #define buffer (G.buffer ) |
| + | #define flines (G.flines ) |
| + | #define empty_line_marker (G.empty_line_marker ) |
| + | #define num_files (G.num_files ) |
| + | #define current_file (G.current_file ) |
| + | #define filename (G.filename ) |
| + | #define files (G.files ) |
| + | #define num_marks (G.num_marks ) |
| + | #define mark_lines (G.mark_lines ) |
| + | #define match_lines (G.match_lines ) |
| + | #define match_pos (G.match_pos ) |
| + | #define num_matches (G.num_matches ) |
| + | #define pattern (G.pattern ) |
| + | #define pattern_valid (G.pattern_valid ) |
| + | #define terminated (G.terminated ) |
| + | #define term_orig (G.term_orig ) |
| + | #define term_less (G.term_less ) |
| + | #define INIT_G() do { \ |
| + | PTR_TO_GLOBALS = xzalloc(sizeof(G)); \ |
| + | empty_line_marker = "~"; \ |
| + | num_files = 1; \ |
| + | current_file = 1; \ |
| + | eof_error = 1; \ |
| + | terminated = 1; \ |
| + | } while (0) |
| /* Reset terminal input to normal */ | |
| static void set_tty_cooked(void) | |
| @@ -380,12 +413,12 @@ static void cap_cur_fline(int nlines) | |
| } | |
| } | |
| - | static char controls[] = |
| + | static const char controls[] = |
| /* NUL: never encountered; TAB: not converted */ | |
| /**/"\x01\x02\x03\x04\x05\x06\x07\x08" "\x0a\x0b\x0c\x0d\x0e\x0f" | |
| "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" | |
| "\x7f\x9b"; /* DEL and infamous Meta-ESC :( */ | |
| - | static char ctrlconv[] = |
| + | static const char ctrlconv[] = |
| /* '\n': it's a former NUL - subst with '@', not 'J' */ | |
| "\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x40\x4b\x4c\x4d\x4e\x4f" | |
| "\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f"; | |
| @@ -604,7 +637,7 @@ static void getch_nowait(char* input, int sz) | |
| FD_SET(0, &readfds); | |
| } | |
| FD_SET(kbd_fd, &readfds); | |
| - | tcsetattr(kbd_fd, TCSANOW, &term_vi); |
| + | tcsetattr(kbd_fd, TCSANOW, &term_less); |
| select(kbd_fd + 1, &readfds, NULL, NULL, NULL); | |
| input[0] = '\0'; | |
| @@ -668,7 +701,7 @@ static char* less_gets(int sz) | |
| /* I be damned if I know why is it needed *repeatedly*, | |
| * but it is needed. Is it because of stdio? */ | |
| - | tcsetattr(kbd_fd, TCSANOW, &term_vi); |
| + | tcsetattr(kbd_fd, TCSANOW, &term_less); |
| read(kbd_fd, &c, 1); | |
| if (c == 0x0d) | |
| @@ -1244,6 +1277,8 @@ int less_main(int argc, char **argv) | |
| { | |
| int keypress; | |
| + | INIT_G(); |
| + | |
| /* TODO: -x: do not interpret backspace, -xx: tab also */ | |
| /* -xxx: newline also */ | |
| /* -w N: assume width N (-xxx -w 32: hex viewer of sorts) */ | |
| @@ -1283,16 +1318,16 @@ int less_main(int argc, char **argv) | |
| tcgetattr(kbd_fd, &term_orig); | |
| signal(SIGTERM, sig_catcher); | |
| signal(SIGINT, sig_catcher); | |
| - | term_vi = term_orig; |
| - | term_vi.c_lflag &= ~(ICANON | ECHO); |
| - | term_vi.c_iflag &= ~(IXON | ICRNL); |
| - | /*term_vi.c_oflag &= ~ONLCR;*/ |
| - | term_vi.c_cc[VMIN] = 1; |
| - | term_vi.c_cc[VTIME] = 0; |
| + | term_less = term_orig; |
| + | term_less.c_lflag &= ~(ICANON | ECHO); |
| + | term_less.c_iflag &= ~(IXON | ICRNL); |
| + | /*term_less.c_oflag &= ~ONLCR;*/ |
| + | term_less.c_cc[VMIN] = 1; |
| + | term_less.c_cc[VTIME] = 0; |
| /* Want to do it just once, but it doesn't work, */ | |
| /* so we are redoing it (see code above). Mystery... */ | |
| - | /*tcsetattr(kbd_fd, TCSANOW, &term_vi);*/ |
| + | /*tcsetattr(kbd_fd, TCSANOW, &term_less);*/ |
| reinitialize(); | |
| while (1) { | |