summaryrefslogtreecommitdiff
path: root/miscutils/less.c
diff options
context:
space:
mode:
Diffstat (limited to 'miscutils/less.c')
-rw-r--r--miscutils/less.c129
1 files changed, 82 insertions, 47 deletions
diff --git a/miscutils/less.c b/miscutils/less.c
index 3df1f37..d6b71b9 100644
--- a/miscutils/less.c
+++ b/miscutils/less.c
@@ -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) {