util-linux.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/2] more: move couple functions
@ 2018-05-23 22:24 Sami Kerola
  2018-05-23 22:24 ` [PATCH 2/2] more: remove global variables, add struct more_control Sami Kerola
  0 siblings, 1 reply; 5+ messages in thread
From: Sami Kerola @ 2018-05-23 22:24 UTC (permalink / raw)
  To: util-linux; +Cc: Sami Kerola

Earlier commit moved lots of functions to work without declarations, but to
be able to get rid of global variables few more moves is needed.

Reference: a8f98304e6d2f4627ca31f6c661934c92b1095f7
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
---
 text-utils/more.c | 246 +++++++++++++++++++++++-----------------------
 1 file changed, 123 insertions(+), 123 deletions(-)

diff --git a/text-utils/more.c b/text-utils/more.c
index d3317cf9c..603c79003 100644
--- a/text-utils/more.c
+++ b/text-utils/more.c
@@ -306,6 +306,36 @@ static void cleareol(void)
 	putstring(eraseln);
 }
 
+/* magic --
+ *	check for file magic numbers.  This code would best be shared
+ *	with the file(1) program or, perhaps, more should not try to be
+ *	so smart. */
+static int magic(FILE *f, char *fs)
+{
+	signed char twobytes[2];
+
+	/* don't try to look ahead if the input is unseekable */
+	if (fseek(f, 0L, SEEK_SET))
+		return 0;
+
+	if (fread(twobytes, 2, 1, f) == 1) {
+		switch (twobytes[0] + (twobytes[1] << 8)) {
+		case 0407:	/* a.out obj */
+		case 0410:	/* a.out exec */
+		case 0413:	/* a.out demand exec */
+		case 0405:
+		case 0411:
+		case 0177545:
+		case 0x457f:	/* simple ELF detection */
+			printf(_("\n******** %s: Not a text file ********\n\n"),
+			       fs);
+			return 1;
+		}
+	}
+	fseek(f, 0L, SEEK_SET);	/* rewind() not necessary */
+	return 0;
+}
+
 /* Check whether the file named by fs is an ASCII file which the user may
  * access.  If it is, return the opened file.  Otherwise return NULL. */
 static FILE *checkf(register char *fs, int *clearfirst)
@@ -343,36 +373,6 @@ static FILE *checkf(register char *fs, int *clearfirst)
 	return (f);
 }
 
-/* magic --
- *	check for file magic numbers.  This code would best be shared
- *	with the file(1) program or, perhaps, more should not try to be
- *	so smart. */
-static int magic(FILE *f, char *fs)
-{
-	signed char twobytes[2];
-
-	/* don't try to look ahead if the input is unseekable */
-	if (fseek(f, 0L, SEEK_SET))
-		return 0;
-
-	if (fread(twobytes, 2, 1, f) == 1) {
-		switch (twobytes[0] + (twobytes[1] << 8)) {
-		case 0407:	/* a.out obj */
-		case 0410:	/* a.out exec */
-		case 0413:	/* a.out demand exec */
-		case 0405:
-		case 0411:
-		case 0177545:
-		case 0x457f:	/* simple ELF detection */
-			printf(_("\n******** %s: Not a text file ********\n\n"),
-			       fs);
-			return 1;
-		}
-	}
-	fseek(f, 0L, SEEK_SET);	/* rewind() not necessary */
-	return 0;
-}
-
 static void prepare_line_buffer(void)
 {
 	char *nline;
@@ -737,6 +737,53 @@ static void prompt(char *filename)
 	inwait++;
 }
 
+static int ourputch(int c)
+{
+	return putc(c, stdout);
+}
+
+static void reset_tty(void)
+{
+	if (no_tty)
+		return;
+	if (pstate) {
+		/* putchar - if that isn't a macro */
+		tputs(ULexit, fileno(stdout), ourputch);
+		fflush(stdout);
+		pstate = 0;
+	}
+	otty.c_lflag |= ICANON | ECHO;
+	otty.c_cc[VMIN] = savetty0.c_cc[VMIN];
+	otty.c_cc[VTIME] = savetty0.c_cc[VTIME];
+	stty(fileno(stderr), &savetty0);
+}
+
+/* Clean up terminal state and exit. Also come here if interrupt signal received */
+static void __attribute__((__noreturn__)) end_it(int dummy __attribute__((__unused__)))
+{
+	/* May be executed as a signal handler as well as by main process.
+	 *
+	 * The _exit() may wait for pending I/O for really long time, be sure
+	 * that signal handler is not executed in this time to avoid double
+	 * de-initialization (free() calls, etc.).
+	 */
+	signal(SIGINT, SIG_IGN);
+
+	reset_tty();
+	if (clreol) {
+		putchar('\r');
+		clreos();
+		fflush(stdout);
+	} else if (!clreol && (promptlen > 0)) {
+		kill_line();
+		fflush(stdout);
+	} else
+		putcerr('\n');
+	free(previousre);
+	free(Line);
+	_exit(EXIT_SUCCESS);
+}
+
 static int readch(void)
 {
 	unsigned char c;
@@ -1011,33 +1058,60 @@ static int expand(char **outbuf, char *inbuf)
 	return (changed);
 }
 
-static int ourputch(int c)
+static void set_tty(void)
 {
-	return putc(c, stdout);
+	otty.c_lflag &= ~(ICANON | ECHO);
+	otty.c_cc[VMIN] = 1;	/* read at least 1 char */
+	otty.c_cc[VTIME] = 0;	/* no timeout */
+	stty(fileno(stderr), &otty);
 }
 
-static void reset_tty(void)
+/* Come here if a quit signal is received */
+static void onquit(int dummy __attribute__((__unused__)))
 {
-	if (no_tty)
-		return;
-	if (pstate) {
-		/* putchar - if that isn't a macro */
-		tputs(ULexit, fileno(stdout), ourputch);
-		fflush(stdout);
-		pstate = 0;
+	signal(SIGQUIT, SIG_IGN);
+	if (!inwait) {
+		putchar('\n');
+		if (!startup) {
+			signal(SIGQUIT, onquit);
+			siglongjmp(restore, 1);
+		} else
+			Pause++;
+	} else if (!dum_opt && notell) {
+		promptlen += fprintf(stderr, _("[Use q or Q to quit]"));
+		notell = 0;
 	}
-	otty.c_lflag |= ICANON | ECHO;
-	otty.c_cc[VMIN] = savetty0.c_cc[VMIN];
-	otty.c_cc[VTIME] = savetty0.c_cc[VTIME];
-	stty(fileno(stderr), &savetty0);
+	signal(SIGQUIT, onquit);
 }
 
-static void set_tty(void)
+/* Come here when we get a suspend signal from the terminal */
+static void onsusp(int dummy __attribute__((__unused__)))
 {
-	otty.c_lflag &= ~(ICANON | ECHO);
-	otty.c_cc[VMIN] = 1;	/* read at least 1 char */
-	otty.c_cc[VTIME] = 0;	/* no timeout */
-	stty(fileno(stderr), &otty);
+	sigset_t signals, oldmask;
+
+	/* ignore SIGTTOU so we don't get stopped if csh grabs the tty */
+	signal(SIGTTOU, SIG_IGN);
+	reset_tty();
+	fflush(stdout);
+	signal(SIGTTOU, SIG_DFL);
+	/* Send the TSTP signal to suspend our process group */
+	signal(SIGTSTP, SIG_DFL);
+
+	/* unblock SIGTSTP or we won't be able to suspend ourself */
+	sigemptyset(&signals);
+	sigaddset(&signals, SIGTSTP);
+	sigprocmask(SIG_UNBLOCK, &signals, &oldmask);
+
+	kill(0, SIGTSTP);
+	/* Pause for station break */
+
+	sigprocmask(SIG_SETMASK, &oldmask, NULL);
+
+	/* We're back */
+	signal(SIGTSTP, onsusp);
+	set_tty();
+	if (inwait)
+		siglongjmp(restore, 1);
 }
 
 static void execute(char *filename, char *cmd, ...)
@@ -1688,24 +1762,6 @@ static void screen(register FILE *f, register int num_lines)
 	}
 }
 
-/* Come here if a quit signal is received */
-static void onquit(int dummy __attribute__((__unused__)))
-{
-	signal(SIGQUIT, SIG_IGN);
-	if (!inwait) {
-		putchar('\n');
-		if (!startup) {
-			signal(SIGQUIT, onquit);
-			siglongjmp(restore, 1);
-		} else
-			Pause++;
-	} else if (!dum_opt && notell) {
-		promptlen += fprintf(stderr, _("[Use q or Q to quit]"));
-		notell = 0;
-	}
-	signal(SIGQUIT, onquit);
-}
-
 /* Come here if a signal for a window size change is received */
 #ifdef SIGWINCH
 static void chgwinsz(int dummy __attribute__((__unused__)))
@@ -1728,32 +1784,6 @@ static void chgwinsz(int dummy __attribute__((__unused__)))
 }
 #endif				/* SIGWINCH */
 
-/* Clean up terminal state and exit. Also come here if interrupt signal received */
-static void __attribute__((__noreturn__)) end_it(int dummy __attribute__((__unused__)))
-{
-	/* May be executed as a signal handler as well as by main process.
-	 *
-	 * The _exit() may wait for pending I/O for really long time, be sure
-	 * that signal handler is not executed in this time to avoid double
-	 * de-initialization (free() calls, etc.).
-	 */
-	signal(SIGINT, SIG_IGN);
-
-	reset_tty();
-	if (clreol) {
-		putchar('\r');
-		clreos();
-		fflush(stdout);
-	} else if (!clreol && (promptlen > 0)) {
-		kill_line();
-		fflush(stdout);
-	} else
-		putcerr('\n');
-	free(previousre);
-	free(Line);
-	_exit(EXIT_SUCCESS);
-}
-
 static void copy_file(register FILE *f)
 {
 	char buf[BUFSIZ];
@@ -1896,36 +1926,6 @@ static void initterm(void)
 	}
 }
 
-/* Come here when we get a suspend signal from the terminal */
-static void onsusp(int dummy __attribute__((__unused__)))
-{
-	sigset_t signals, oldmask;
-
-	/* ignore SIGTTOU so we don't get stopped if csh grabs the tty */
-	signal(SIGTTOU, SIG_IGN);
-	reset_tty();
-	fflush(stdout);
-	signal(SIGTTOU, SIG_DFL);
-	/* Send the TSTP signal to suspend our process group */
-	signal(SIGTSTP, SIG_DFL);
-
-	/* unblock SIGTSTP or we won't be able to suspend ourself */
-	sigemptyset(&signals);
-	sigaddset(&signals, SIGTSTP);
-	sigprocmask(SIG_UNBLOCK, &signals, &oldmask);
-
-	kill(0, SIGTSTP);
-	/* Pause for station break */
-
-	sigprocmask(SIG_SETMASK, &oldmask, NULL);
-
-	/* We're back */
-	signal(SIGTSTP, onsusp);
-	set_tty();
-	if (inwait)
-		siglongjmp(restore, 1);
-}
-
 int main(int argc, char **argv)
 {
 	FILE *f;
-- 
2.17.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 2/2] more: remove global variables, add struct more_control
  2018-05-23 22:24 [PATCH 1/2] more: move couple functions Sami Kerola
@ 2018-05-23 22:24 ` Sami Kerola
  2018-05-24  7:10   ` Karel Zak
  0 siblings, 1 reply; 5+ messages in thread
From: Sami Kerola @ 2018-05-23 22:24 UTC (permalink / raw)
  To: util-linux; +Cc: Sami Kerola

This is rather big change, but that is the only way to do this sort job.  To
keep this change relatively understandable only moves global variables to a
state structure.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
---
 text-utils/more.c | 1316 +++++++++++++++++++++++----------------------
 1 file changed, 672 insertions(+), 644 deletions(-)

diff --git a/text-utils/more.c b/text-utils/more.c
index 603c79003..03aae421f 100644
--- a/text-utils/more.c
+++ b/text-utils/more.c
@@ -85,11 +85,11 @@
 
 #define VI	"vi"	/* found on the user's path */
 
-#define Fopen(s,m)	(Currline = 0,file_pos=0,fopen(s,m))
-#define Ftell(f)	file_pos
-#define Fseek(f,off)	(file_pos=off,fseek(f,off,0))
-#define Getc(f)		(++file_pos, getc(f))
-#define Ungetc(c,f)	(--file_pos, ungetc(c,f))
+#define Fopen(s,m)	(ctl->Currline = 0, ctl->file_pos=0, fopen(s,m))
+#define Ftell(f)	ctl->file_pos
+#define Fseek(f,off)	(ctl->file_pos=off, fseek(f, off, 0))
+#define Getc(f)		(++ctl->file_pos, getc(f))
+#define Ungetc(c,f)	(--ctl->file_pos, ungetc(c,f))
 #define putcerr(c)	fputc(c, stderr)
 #define putserr(s)	fputs(s, stderr)
 #define putsout(s)	fputs(s, stdout)
@@ -99,9 +99,9 @@
 #define ERASEONECOLUMN(x) \
 		do { \
 		    if (x) \
-			putserr(BSB); \
+			putserr("\b \b"); \
 		    else \
-			putserr(BS); \
+			putserr("\b"); \
 		} while(0)
 
 #define TBUFSIZ		1024
@@ -142,69 +142,83 @@
 #define TERM_UNDERLINE_CHAR       "uc"
 #define TERM_UNDERLINE            "ul"
 
-static struct termios otty, savetty0;
-static long file_pos, file_size;
-static int fnum, no_intty, no_tty;
-static int dum_opt, dlines;
-static void onquit(int), onsusp(int), chgwinsz(int), end_it(int);
-static int nscroll = SCROLL_LEN;	/* Number of lines scrolled by 'd' */
-static int fold_opt = 1;		/* Fold long lines */
-static int stop_opt = 1;		/* Stop after form feeds */
-static int ssp_opt = 0;			/* Suppress white space */
-static int ul_opt = 1;			/* Underline as best we can */
-static int promptlen;
-static int Currline;			/* Line we are currently at */
-static int startup = 1;
-static int firstf = 1;
-static int notell = 1;
-static int docrterase = 0;
-static int docrtkill = 0;
-static int bad_so;			/* True if overwriting does not turn
-					   off standout */
-static int inwait, Pause, errors;
-static int within;			/* true if we are within a file,
-					   false if we are between files */
-static int hard, dumb, noscroll, hardtabs, clreol, eatnl;
-static int catch_susp;			/* We should catch the SIGTSTP signal */
-static char **fnames;			/* The list of file names */
-static int nfiles;			/* Number of files left to process */
-static char *shell;			/* The name of the shell to use */
-static int shellp;			/* A previous shell command exists */
-static sigjmp_buf restore;
-static char *Line;			/* Line buffer */
-static size_t LineLen;			/* size of Line buffer */
-static int Lpp = LINES_PER_PAGE;	/* lines per page */
-static char *Clear;			/* clear screen */
-static char *eraseln;			/* erase line */
-static char *Senter, *Sexit;		/* enter and exit standout mode */
-static char *ULenter, *ULexit;		/* enter and exit underline mode */
-static char *chUL;			/* underline character */
-static char *chBS;			/* backspace character */
-static char *Home;			/* go to home */
-static char *cursorm;			/* cursor movement */
-static char cursorhome[40];		/* contains cursor movement to home */
-static char *EodClr;			/* clear rest of screen */
-static int Mcol = NUM_COLUMNS;		/* number of columns */
-static int Wrap = 1;			/* set if automargins */
-static int soglitch;			/* terminal has standout mode glitch */
-static int ulglitch;			/* terminal has underline mode glitch */
-static int pstate = 0;			/* current UL state */
-static int magic(FILE *, char *);
-static char *previousre;		/* previous search() buf[] item */
-static struct {
-	long chrctr, line;
-} context, screen_start;
-extern char PC;			/* pad character */
-
-static char *BS = "\b";
-static char *BSB = "\b \b";
-static char *CARAT = "^";
-
-static char ch;
-static int lastcmd, lastarg, lastp;
-static int lastcolon;
-static char shell_line[SHELL_LINE];
-
+struct more_control {
+	struct termios otty;		/* output terminal */
+	struct termios savetty0;	/* original terminal settings */
+	long file_pos;			/* file position */
+	long file_size;			/* file size */
+	int fnum;			/* argv[] position */
+	int dlines;			/* screen size in lines */
+	int nscroll;			/* number of lines scrolled by 'd' */
+	int promptlen;			/* message prompt length */
+	int Currline;			/* line we are currently at */
+	char **fnames;			/* The list of file names */
+	int nfiles;			/* Number of files left to process */
+	char *shell;			/* name of the shell to use */
+	int shellp;			/* does previous shell command exist */
+	sigjmp_buf restore;		/* siglongjmp() destination */
+	char *Line;			/* line buffer */
+	size_t LineLen;			/* size of Line buffer */
+	int Lpp;			/* lines per page */
+	char *Clear;			/* clear screen */
+	char *eraseln;			/* erase line */
+	char *Senter;			/* enter standout mode */
+	char *Sexit;			/* exit standout mode */
+	char *ULenter;			/* enter underline mode */
+	char *ULexit;			/* exit underline mode */
+	char *chUL;			/* underline character */
+	char *chBS;			/* backspace character */
+	char *Home;			/* go to home */
+	char *cursorm;			/* cursor movement */
+	char cursorhome[40];		/* contains cursor movement to home */
+	char *EodClr;			/* clear rest of screen */
+	int Mcol;			/* number of columns */
+	char *previousre;		/* previous search() buf[] item */
+	struct {
+		long chrctr;		/* row number */
+		long line;		/* line number */
+	} context,
+	  screen_start;
+	char ch;
+	int lastcmd;			/* previous more key command */
+	int lastarg;			/* previous key command argument */
+	int lastcolon;			/* is a colon-prefixed key command */
+	char shell_line[SHELL_LINE];
+	char PC;			/* pad character */
+	uint32_t
+		bad_so:1,		/* true if overwriting does not turn off standout */
+		catch_susp:1,		/* we should catch the SIGTSTP signal */
+		clreol:1,		/* do not scroll, paint each screen from the top */
+		docrterase:1,		/* is erase previous supported */
+		docrtkill:1,		/* is erase input supported */
+		dumb:1,			/* is terminal type known */
+		dum_opt:1,		/* suppress bell */
+		eatnl:1,		/* is newline ignored after 80 cols */
+		errors:1,		/* is an error reported */
+		firstf:1,		/* is the input file the first in list */
+		fold_opt:1,		/* fold long lines */
+		hard:1,			/* is this hard copy terminal (a printer or such) */
+		hardtabs:1,		/* print spaces instead of '\t' */
+		inwait:1,		/* is waiting user input */
+		lastp:1,		/* run previous key command */
+		no_intty:1,		/* is input in interactive mode */
+		noscroll:1,		/* do not scroll, clear the screen and then display text */
+		notell:1,		/* suppress quit dialog */
+		no_tty:1,		/* is output in interactive mode */
+		Pause:1,		/* is output paused */
+		pstate:1,		/* current UL state */
+		soglitch:1,		/* terminal has standout mode glitch */
+		ssp_opt:1,		/* suppress white space */
+		startup:1,		/* is startup completed */
+		stop_opt:1,		/* stop after form feeds */
+		ulglitch:1,		/* terminal has underline mode glitch */
+		ul_opt:1,		/* underline as best we can */
+		within:1,		/* true if we are within a file, false if we are between files */
+		Wrap:1;			/* set if automargins */
+};
+
+/* FIXME: global_ctl is used in signal handlers. */
+struct more_control *global_ctl;
 
 static void putstring(char *s)
 {
@@ -240,7 +254,7 @@ static void __attribute__((__noreturn__)) usage(void)
 }
 
 
-static void argscan(char *s)
+static void argscan(struct more_control *ctl, char *s)
 {
 	int seen_num = 0;
 
@@ -257,31 +271,31 @@ static void argscan(char *s)
 		case '8':
 		case '9':
 			if (!seen_num) {
-				dlines = 0;
+				ctl->dlines = 0;
 				seen_num = 1;
 			}
-			dlines = dlines * 10 + *s - '0';
+			ctl->dlines = ctl->dlines * 10 + *s - '0';
 			break;
 		case 'd':
-			dum_opt = 1;
+			ctl->dum_opt = 1;
 			break;
 		case 'l':
-			stop_opt = 0;
+			ctl->stop_opt = 0;
 			break;
 		case 'f':
-			fold_opt = 0;
+			ctl->fold_opt = 0;
 			break;
 		case 'p':
-			noscroll++;
+			ctl->noscroll = 1;
 			break;
 		case 'c':
-			clreol++;
+			ctl->clreol = 1;
 			break;
 		case 's':
-			ssp_opt = 1;
+			ctl->ssp_opt = 1;
 			break;
 		case 'u':
-			ul_opt = 0;
+			ctl->ul_opt = 0;
 			break;
 		case '-':
 		case ' ':
@@ -301,9 +315,9 @@ static void argscan(char *s)
 }
 
 /* force clear to end of line */
-static void cleareol(void)
+static void cleareol(struct more_control *ctl)
 {
-	putstring(eraseln);
+	putstring(ctl->eraseln);
 }
 
 /* magic --
@@ -338,7 +352,7 @@ static int magic(FILE *f, char *fs)
 
 /* Check whether the file named by fs is an ASCII file which the user may
  * access.  If it is, return the opened file.  Otherwise return NULL. */
-static FILE *checkf(register char *fs, int *clearfirst)
+static FILE *checkf(struct more_control *ctl, register char *fs, int *clearfirst)
 {
 	struct stat stbuf;
 	register FILE *f;
@@ -346,8 +360,8 @@ static FILE *checkf(register char *fs, int *clearfirst)
 
 	if (stat(fs, &stbuf) == -1) {
 		fflush(stdout);
-		if (clreol)
-			cleareol();
+		if (ctl->clreol)
+			cleareol(ctl);
 		warn(_("stat of %s failed"), fs);
 		return ((FILE *)NULL);
 	}
@@ -368,30 +382,30 @@ static FILE *checkf(register char *fs, int *clearfirst)
 	c = Getc(f);
 	*clearfirst = (c == '\f');
 	Ungetc(c, f);
-	if ((file_size = stbuf.st_size) == 0)
-		file_size = LONG_MAX;
+	if ((ctl->file_size = stbuf.st_size) == 0)
+		ctl->file_size = LONG_MAX;
 	return (f);
 }
 
-static void prepare_line_buffer(void)
+static void prepare_line_buffer(struct more_control *ctl)
 {
 	char *nline;
-	size_t nsz = Mcol * 4;
+	size_t nsz = ctl->Mcol * 4;
 
-	if (LineLen >= nsz)
+	if (ctl->LineLen >= nsz)
 		return;
 
 	if (nsz < LINSIZ)
 		nsz = LINSIZ;
 
 	/* alloc nsz and extra space for \n\0 */
-	nline = xrealloc(Line, nsz + 2);
-	Line = nline;
-	LineLen = nsz;
+	nline = xrealloc(ctl->Line, nsz + 2);
+	ctl->Line = nline;
+	ctl->LineLen = nsz;
 }
 
 /* Get a logical line */
-static int get_line(register FILE *f, int *length)
+static int get_line(struct more_control *ctl, register FILE *f, int *length)
 {
 	int c;
 	char *p;
@@ -413,18 +427,18 @@ static int get_line(register FILE *f, int *length)
 	memset(&state, '\0', sizeof(mbstate_t));
 #endif
 
-	prepare_line_buffer();
+	prepare_line_buffer(ctl);
 
-	p = Line;
+	p = ctl->Line;
 	column = 0;
 	c = Getc(f);
 	if (colflg && c == '\n') {
-		Currline++;
+		ctl->Currline++;
 		c = Getc(f);
 	}
-	while (p < &Line[LineLen - 1]) {
+	while (p < &ctl->Line[ctl->LineLen - 1]) {
 #ifdef HAVE_WIDECHAR
-		if (fold_opt && use_mbc_buffer_flag && MB_CUR_MAX > 1) {
+		if (ctl->fold_opt && use_mbc_buffer_flag && MB_CUR_MAX > 1) {
 			use_mbc_buffer_flag = 0;
 			state_bak = state;
 			mbc[mbc_pos++] = c;
@@ -443,7 +457,7 @@ static int get_line(register FILE *f, int *length)
 				column++;
 				file_pos_bak++;
 
-				if (column >= Mcol) {
+				if (column >= ctl->Mcol) {
 					Fseek(f, file_pos_bak);
 				} else {
 					memmove(mbc, mbc + 1, --mbc_pos);
@@ -457,11 +471,11 @@ static int get_line(register FILE *f, int *length)
 			default:
 				wc_width = wcwidth(wc);
 
-				if (column + wc_width > Mcol) {
+				if (column + wc_width > ctl->Mcol) {
 					Fseek(f, file_pos_bak);
 					break_flag = 1;
 				} else {
-					for (i = 0; p < &Line[LineLen - 1] &&
+					for (i = 0; p < &ctl->Line[ctl->LineLen - 1] &&
 						    i < mbc_pos; i++)
 						*p++ = mbc[i];
 					if (wc_width > 0)
@@ -469,7 +483,7 @@ static int get_line(register FILE *f, int *length)
 				}
 			}
 
-			if (break_flag || column >= Mcol)
+			if (break_flag || column >= ctl->Mcol)
 				break;
 
 			c = Getc(f);
@@ -477,16 +491,16 @@ static int get_line(register FILE *f, int *length)
 		}
 #endif	/* HAVE_WIDECHAR */
 		if (c == EOF) {
-			if (p > Line) {
+			if (p > ctl->Line) {
 				*p = '\0';
-				*length = p - Line;
+				*length = p - ctl->Line;
 				return (column);
 			}
-			*length = p - Line;
+			*length = p - ctl->Line;
 			return (EOF);
 		}
 		if (c == '\n') {
-			Currline++;
+			ctl->Currline++;
 			break;
 		}
 
@@ -506,19 +520,19 @@ static int get_line(register FILE *f, int *length)
 		}
 #endif	/* 0 */
 		if (c == '\t') {
-			if (!hardtabs || (column < promptlen && !hard)) {
-				if (hardtabs && eraseln && !dumb) {
+			if (!ctl->hardtabs || (column < ctl->promptlen && !ctl->hard)) {
+				if (ctl->hardtabs && ctl->eraseln && !ctl->dumb) {
 					column = 1 + (column | 7);
-					putstring(eraseln);
-					promptlen = 0;
+					putp(ctl->eraseln);
+					ctl->promptlen = 0;
 				} else {
-					for (--p; p < &Line[LineLen - 1];) {
+					for (--p; p < &ctl->Line[ctl->LineLen - 1];) {
 						*p++ = ' ';
 						if ((++column & 7) == 0)
 							break;
 					}
-					if (column >= promptlen)
-						promptlen = 0;
+					if (column >= ctl->promptlen)
+						ctl->promptlen = 0;
 				}
 			} else
 				column = 1 + (column | 7);
@@ -528,22 +542,22 @@ static int get_line(register FILE *f, int *length)
 			int next = Getc(f);
 			if (next == '\n') {
 				p--;
-				Currline++;
+				ctl->Currline++;
 				break;
 			}
 			Ungetc(next, f);
 			column = 0;
-		} else if (c == '\f' && stop_opt) {
+		} else if (c == '\f' && ctl->stop_opt) {
 			p[-1] = '^';
 			*p++ = 'L';
 			column += 2;
-			Pause++;
+			ctl->Pause = 1;
 		} else if (c == EOF) {
-			*length = p - Line;
+			*length = p - ctl->Line;
 			return (column);
 		} else {
 #ifdef HAVE_WIDECHAR
-			if (fold_opt && MB_CUR_MAX > 1) {
+			if (ctl->fold_opt && MB_CUR_MAX > 1) {
 				memset(mbc, '\0', MB_LEN_MAX);
 				mbc_pos = 0;
 				mbc[mbc_pos++] = c;
@@ -577,52 +591,52 @@ static int get_line(register FILE *f, int *length)
 			}
 		}
 
-		if (column >= Mcol && fold_opt)
+		if (column >= ctl->Mcol && ctl->fold_opt)
 			break;
 #ifdef HAVE_WIDECHAR
-		if (use_mbc_buffer_flag == 0 && p >= &Line[LineLen - 1 - 4])
+		if (use_mbc_buffer_flag == 0 && p >= &ctl->Line[ctl->LineLen - 1 - 4])
 			/* don't read another char if there is no space for
 			 * whole multibyte sequence */
 			break;
 #endif
 		c = Getc(f);
 	}
-	if (column >= Mcol && Mcol > 0) {
-		if (!Wrap) {
+	if (column >= ctl->Mcol && ctl->Mcol > 0) {
+		if (!ctl->Wrap) {
 			*p++ = '\n';
 		}
 	}
-	colflg = column == Mcol && fold_opt;
-	if (colflg && eatnl && Wrap) {
+	colflg = column == ctl->Mcol && ctl->fold_opt;
+	if (colflg && ctl->eatnl && ctl->Wrap) {
 		*p++ = '\n';	/* simulate normal wrap */
 	}
-	*length = p - Line;
+	*length = p - ctl->Line;
 	*p = 0;
 	return (column);
 }
 
-static void clreos(void)
+static void clreos(struct more_control *ctl)
 {
-	putstring(EodClr);
+	putstring(ctl->EodClr);
 }
 
 /* Erase the rest of the prompt, assuming we are starting at column col. */
-static void erasep(register int col)
+static void erasep(struct more_control *ctl, register int col)
 {
 
-	if (promptlen == 0)
+	if (ctl->promptlen == 0)
 		return;
-	if (hard) {
+	if (ctl->hard) {
 		putchar('\n');
 	} else {
 		if (col == 0)
 			putchar('\r');
-		if (!dumb && eraseln)
-			putstring(eraseln);
+		if (!ctl->dumb && ctl->eraseln)
+			putstring(ctl->eraseln);
 		else
-			printf("%*s", promptlen - col, "");
+			printf("%*s", ctl->promptlen - col, "");
 	}
-	promptlen = 0;
+	ctl->promptlen = 0;
 }
 
 #ifdef HAVE_WIDECHAR
@@ -637,17 +651,17 @@ static UL_ASAN_BLACKLIST size_t xmbrtowc(wchar_t *wc, const char *s, size_t n,
 #endif
 
 /* Print a buffer of n characters */
-static void prbuf(register char *s, register int n)
+static void prbuf(struct more_control *ctl, register char *s, register int n)
 {
 	register char c;	/* next output character */
 	register int state;	/* next output char's UL state */
 #define wouldul(s,n)	((n) >= 2 && (((s)[0] == '_' && (s)[1] == '\b') || ((s)[1] == '\b' && (s)[2] == '_')))
 
 	while (--n >= 0)
-		if (!ul_opt)
+		if (!ctl->ul_opt)
 			putchar(*s++);
 		else {
-			if (*s == ' ' && pstate == 0 && ulglitch
+			if (*s == ' ' && ctl->pstate == 0 && ctl->ulglitch
 			    && wouldul(s + 1, n - 1)) {
 				s++;
 				continue;
@@ -658,15 +672,15 @@ static void prbuf(register char *s, register int n)
 				s += 3;
 			} else
 				c = *s++;
-			if (state != pstate) {
-				if (c == ' ' && state == 0 && ulglitch
+			if (state != ctl->pstate) {
+				if (c == ' ' && state == 0 && ctl->ulglitch
 				    && wouldul(s, n - 1))
 					state = 1;
 				else
-					putstring(state ? ULenter : ULexit);
+					putp(state ? ctl->ULenter : ctl->ULexit);
 			}
-			if (c != ' ' || pstate == 0 || state != 0
-			    || ulglitch == 0)
+			if (c != ' ' || ctl->pstate == 0 || state != 0
+			    || ctl->ulglitch == 0)
 #ifdef HAVE_WIDECHAR
 			{
 				wchar_t wc;
@@ -683,58 +697,58 @@ static void prbuf(register char *s, register int n)
 #else
 				putchar(c);
 #endif				/* HAVE_WIDECHAR */
-			if (state && *chUL) {
-				putsout(chBS);
-				putstring(chUL);
+			if (state && *ctl->chUL) {
+				putsout(ctl->chBS);
+				putstring(ctl->chUL);
 			}
-			pstate = state;
+			ctl->pstate = state;
 		}
 }
 
 /* Erase the current line entirely */
-static void kill_line(void)
+static void kill_line(struct more_control *ctl)
 {
-	erasep(0);
-	if (!eraseln || dumb)
+	erasep(ctl, 0);
+	if (!ctl->eraseln || ctl->dumb)
 		putchar('\r');
 }
 
 #define ringbell()	putcerr('\007')
 
-static void prompt(char *filename)
+static void prompt(struct more_control *ctl, char *filename)
 {
-	if (clreol)
-		cleareol();
-	else if (promptlen > 0)
-		kill_line();
-	if (!hard) {
-		promptlen = 0;
-		if (Senter && Sexit) {
-			putstring(Senter);
-			promptlen += (2 * soglitch);
+	if (ctl->clreol)
+		cleareol(ctl);
+	else if (ctl->promptlen > 0)
+		kill_line(ctl);
+	if (!ctl->hard) {
+		ctl->promptlen = 0;
+		if (ctl->Senter && ctl->Sexit) {
+			putstring(ctl->Senter);
+			ctl->promptlen += (2 * ctl->soglitch);
 		}
-		if (clreol)
-			cleareol();
-		promptlen += printf(_("--More--"));
+		if (ctl->clreol)
+			cleareol(ctl);
+		ctl->promptlen += printf(_("--More--"));
 		if (filename != NULL) {
-			promptlen += printf(_("(Next file: %s)"), filename);
-		} else if (!no_intty) {
-			promptlen +=
+			ctl->promptlen += printf(_("(Next file: %s)"), filename);
+		} else if (!ctl->no_intty) {
+			ctl->promptlen +=
 			    printf("(%d%%)",
-				   (int)((file_pos * 100) / file_size));
+				   (int)((ctl->file_pos * 100) / ctl->file_size));
 		}
-		if (dum_opt) {
-			promptlen +=
+		if (ctl->dum_opt) {
+			ctl->promptlen +=
 			    printf(_("[Press space to continue, 'q' to quit.]"));
 		}
-		if (Senter && Sexit)
-			putstring(Sexit);
-		if (clreol)
-			clreos();
+		if (ctl->Senter && ctl->Sexit)
+			putstring(ctl->Sexit);
+		if (ctl->clreol)
+			clreos(ctl);
 		fflush(stdout);
 	} else
 		ringbell();
-	inwait++;
+	ctl->inwait++;
 }
 
 static int ourputch(int c)
@@ -744,18 +758,18 @@ static int ourputch(int c)
 
 static void reset_tty(void)
 {
-	if (no_tty)
+	if (global_ctl->no_tty)
 		return;
-	if (pstate) {
+	if (global_ctl->pstate) {
 		/* putchar - if that isn't a macro */
-		tputs(ULexit, fileno(stdout), ourputch);
+		tputs(global_ctl->ULexit, fileno(stdout), ourputch);
 		fflush(stdout);
-		pstate = 0;
+		global_ctl->pstate = 0;
 	}
-	otty.c_lflag |= ICANON | ECHO;
-	otty.c_cc[VMIN] = savetty0.c_cc[VMIN];
-	otty.c_cc[VTIME] = savetty0.c_cc[VTIME];
-	stty(fileno(stderr), &savetty0);
+	global_ctl->otty.c_lflag |= ICANON | ECHO;
+	global_ctl->otty.c_cc[VMIN] = global_ctl->savetty0.c_cc[VMIN];
+	global_ctl->otty.c_cc[VTIME] = global_ctl->savetty0.c_cc[VTIME];
+	stty(fileno(stderr), &global_ctl->savetty0);
 }
 
 /* Clean up terminal state and exit. Also come here if interrupt signal received */
@@ -770,21 +784,21 @@ static void __attribute__((__noreturn__)) end_it(int dummy __attribute__((__unus
 	signal(SIGINT, SIG_IGN);
 
 	reset_tty();
-	if (clreol) {
+	if (global_ctl->clreol) {
 		putchar('\r');
-		clreos();
+		clreos(global_ctl);
 		fflush(stdout);
-	} else if (!clreol && (promptlen > 0)) {
-		kill_line();
+	} else if (!global_ctl->clreol && (global_ctl->promptlen > 0)) {
+		kill_line(global_ctl);
 		fflush(stdout);
 	} else
 		putcerr('\n');
-	free(previousre);
-	free(Line);
+	free(global_ctl->previousre);
+	free(global_ctl->Line);
 	_exit(EXIT_SUCCESS);
 }
 
-static int readch(void)
+static int readch(struct more_control *ctl)
 {
 	unsigned char c;
 
@@ -793,27 +807,27 @@ static int readch(void)
 		if (errno != EINTR)
 			end_it(0);
 		else
-			c = otty.c_cc[VKILL];
+			c = ctl->otty.c_cc[VKILL];
 	}
 	return (c);
 }
 
 /* Read a decimal number from the terminal.  Set cmd to the non-digit
  * which terminates the number. */
-static int number(char *cmd)
+static int number(struct more_control *ctl, char *cmd)
 {
 	register int i;
 
 	i = 0;
-	ch = otty.c_cc[VKILL];
+	ctl->ch = ctl->otty.c_cc[VKILL];
 	for (;;) {
-		ch = readch();
-		if (isdigit(ch))
-			i = i * 10 + ch - '0';
-		else if ((cc_t) ch == otty.c_cc[VKILL])
+		ctl->ch = readch(ctl);
+		if (isdigit(ctl->ch))
+			i = i * 10 + ctl->ch - '0';
+		else if ((cc_t) ctl->ch == ctl->otty.c_cc[VKILL])
 			i = 0;
 		else {
-			*cmd = ch;
+			*cmd = ctl->ch;
 			break;
 		}
 	}
@@ -822,62 +836,62 @@ static int number(char *cmd)
 
 /* Skip nskip files in the file list (from the command line).  Nskip may
  * be negative. */
-static void skipf(register int nskip)
+static void skipf(struct more_control *ctl, register int nskip)
 {
 	if (nskip == 0)
 		return;
 	if (nskip > 0) {
-		if (fnum + nskip > nfiles - 1)
-			nskip = nfiles - fnum - 1;
-	} else if (within)
-		++fnum;
-	fnum += nskip;
-	if (fnum < 0)
-		fnum = 0;
+		if (ctl->fnum + nskip > ctl->nfiles - 1)
+			nskip = ctl->nfiles - ctl->fnum - 1;
+	} else if (ctl->within)
+		ctl->fnum++;
+	ctl->fnum += nskip;
+	if (ctl->fnum < 0)
+		ctl->fnum = 0;
 	puts(_("\n...Skipping "));
-	if (clreol)
-		cleareol();
+	if (ctl->clreol)
+		cleareol(ctl);
 	if (nskip > 0)
 		putsout(_("...Skipping to file "));
 	else
 		putsout(_("...Skipping back to file "));
-	puts(fnames[fnum]);
-	if (clreol)
-		cleareol();
+	puts(ctl->fnames[ctl->fnum]);
+	if (ctl->clreol)
+		cleareol(ctl);
 	putchar('\n');
-	--fnum;
+	ctl->fnum--;
 }
 
-static void show(char c)
+static void show(struct more_control *ctl, char c)
 {
 	if ((c < ' ' && c != '\n' && c != ESC) || c == RUBOUT) {
 		c += (c == RUBOUT) ? -0100 : 0100;
-		putserr(CARAT);
-		promptlen++;
+		putserr("^");
+		ctl->promptlen++;
 	}
 	putcerr(c);
-	promptlen++;
+	ctl->promptlen++;
 }
 
-static void more_error(char *mess)
+static void more_error(struct more_control *ctl, char *mess)
 {
-	if (clreol)
-		cleareol();
+	if (ctl->clreol)
+		cleareol(ctl);
 	else
-		kill_line();
-	promptlen += strlen(mess);
-	if (Senter && Sexit) {
-		putstring(Senter);
+		kill_line(ctl);
+	ctl->promptlen += strlen(mess);
+	if (ctl->Senter && ctl->Sexit) {
+		putp(ctl->Senter);
 		putsout(mess);
-		putstring(Sexit);
+		putp(ctl->Sexit);
 	} else
 		putsout(mess);
 	fflush(stdout);
-	errors++;
-	siglongjmp(restore, 1);
+	ctl->errors++;
+	siglongjmp(ctl->restore, 1);
 }
 
-static void ttyin(char buf[], register int nmax, char pchar)
+static void ttyin(struct more_control *ctl, char buf[], register int nmax, char pchar)
 {
 	char *sp;
 	int c;
@@ -887,12 +901,12 @@ static void ttyin(char buf[], register int nmax, char pchar)
 	sp = buf;
 	maxlen = 0;
 	while (sp - buf < nmax) {
-		if (promptlen > maxlen)
-			maxlen = promptlen;
-		c = readch();
+		if (ctl->promptlen > maxlen)
+			maxlen = ctl->promptlen;
+		c = readch(ctl);
 		if (c == '\\') {
 			slash++;
-		} else if (((cc_t) c == otty.c_cc[VERASE]) && !slash) {
+		} else if (((cc_t) c == ctl->otty.c_cc[VERASE]) && !slash) {
 			if (sp > buf) {
 #ifdef HAVE_WIDECHAR
 				if (MB_CUR_MAX > 1) {
@@ -925,7 +939,7 @@ static void ttyin(char buf[], register int nmax, char pchar)
 					}
 
 					if (mblength == 1) {
-						ERASEONECOLUMN(docrterase);
+						ERASEONECOLUMN(ctl->docrterase);
 					} else {
 						int wc_width;
 						wc_width = wcwidth(wc);
@@ -933,54 +947,54 @@ static void ttyin(char buf[], register int nmax, char pchar)
 						    (wc_width <
 						     1) ? 1 : wc_width;
 						while (wc_width--) {
-							ERASEONECOLUMN(docrterase);
+							ERASEONECOLUMN(ctl->docrterase);
 						}
 					}
 
 					while (mblength--) {
-						--promptlen;
+						--ctl->promptlen;
 						--sp;
 					}
 				} else
 #endif	/* HAVE_WIDECHAR */
 				{
-					--promptlen;
-					ERASEONECOLUMN(docrterase);
+					--ctl->promptlen;
+					ERASEONECOLUMN(ctl->docrterase);
 					--sp;
 				}
 
 				if ((*sp < ' ' && *sp != '\n') || *sp == RUBOUT) {
-					--promptlen;
-					ERASEONECOLUMN(docrterase);
+					--ctl->promptlen;
+					ERASEONECOLUMN(ctl->docrterase);
 				}
 				continue;
 			} else {
-				if (!eraseln)
-					promptlen = maxlen;
-				siglongjmp(restore, 1);
+				if (!ctl->eraseln)
+					ctl->promptlen = maxlen;
+				siglongjmp(ctl->restore, 1);
 			}
-		} else if (((cc_t) c == otty.c_cc[VKILL]) && !slash) {
-			if (hard) {
-				show(c);
+		} else if (((cc_t) c == ctl->otty.c_cc[VKILL]) && !slash) {
+			if (ctl->hard) {
+				show(ctl, c);
 				putchar('\n');
 				putchar(pchar);
 			} else {
 				putchar('\r');
 				putchar(pchar);
-				if (eraseln)
-					erasep(1);
-				else if (docrtkill)
-					while (promptlen-- > 1)
-						putserr(BSB);
-				promptlen = 1;
+				if (ctl->eraseln)
+					erasep(ctl, 1);
+				else if (ctl->docrtkill)
+					while (ctl->promptlen-- > 1)
+						putserr("\b \b");
+				ctl->promptlen = 1;
 			}
 			sp = buf;
 			fflush(stdout);
 			continue;
 		}
-		if (slash && ((cc_t) c == otty.c_cc[VKILL]
-			      || (cc_t) c == otty.c_cc[VERASE])) {
-			ERASEONECOLUMN(docrterase);
+		if (slash && ((cc_t) c == ctl->otty.c_cc[VKILL]
+			      || (cc_t) c == ctl->otty.c_cc[VERASE])) {
+			ERASEONECOLUMN(ctl->docrterase);
 			--sp;
 		}
 		if (c != '\\')
@@ -988,24 +1002,24 @@ static void ttyin(char buf[], register int nmax, char pchar)
 		*sp++ = c;
 		if ((c < ' ' && c != '\n' && c != ESC) || c == RUBOUT) {
 			c += (c == RUBOUT) ? -0100 : 0100;
-			putserr(CARAT);
-			promptlen++;
+			putserr("^");
+			ctl->promptlen++;
 		}
 		if (c != '\n' && c != ESC) {
 			putcerr(c);
-			promptlen++;
+			ctl->promptlen++;
 		} else
 			break;
 	}
 	*--sp = '\0';
-	if (!eraseln)
-		promptlen = maxlen;
+	if (!ctl->eraseln)
+		ctl->promptlen = maxlen;
 	if (sp - buf >= nmax - 1)
-		more_error(_("Line too long"));
+		more_error(ctl, _("Line too long"));
 }
 
 /* return: 0 - unchanged, 1 - changed, -1 - overflow (unchanged) */
-static int expand(char **outbuf, char *inbuf)
+static int expand(struct more_control *ctl, char **outbuf, char *inbuf)
 {
 	char *inpstr;
 	char *outstr;
@@ -1014,7 +1028,7 @@ static int expand(char **outbuf, char *inbuf)
 	int changed = 0;
 	int tempsz, xtra, offset;
 
-	xtra = strlen(fnames[fnum]) + strlen(shell_line) + 1;
+	xtra = strlen(ctl->fnames[ctl->fnum]) + strlen(ctl->shell_line) + 1;
 	tempsz = 200 + xtra;
 	temp = xmalloc(tempsz);
 	inpstr = inbuf;
@@ -1028,19 +1042,19 @@ static int expand(char **outbuf, char *inbuf)
 		}
 		switch (c) {
 		case '%':
-			if (!no_intty) {
-				strcpy(outstr, fnames[fnum]);
-				outstr += strlen(fnames[fnum]);
+			if (!ctl->no_intty) {
+				strcpy(outstr, ctl->fnames[ctl->fnum]);
+				outstr += strlen(ctl->fnames[ctl->fnum]);
 				changed++;
 			} else
 				*outstr++ = c;
 			break;
 		case '!':
-			if (!shellp)
-				more_error(_
+			if (!ctl->shellp)
+				more_error(ctl, _
 					   ("No previous command to substitute for"));
-			strcpy(outstr, shell_line);
-			outstr += strlen(shell_line);
+			strcpy(outstr, ctl->shell_line);
+			outstr += strlen(ctl->shell_line);
 			changed++;
 			break;
 		case '\\':
@@ -1058,28 +1072,28 @@ static int expand(char **outbuf, char *inbuf)
 	return (changed);
 }
 
-static void set_tty(void)
+static void set_tty(struct more_control *ctl)
 {
-	otty.c_lflag &= ~(ICANON | ECHO);
-	otty.c_cc[VMIN] = 1;	/* read at least 1 char */
-	otty.c_cc[VTIME] = 0;	/* no timeout */
-	stty(fileno(stderr), &otty);
+	ctl->otty.c_lflag &= ~(ICANON | ECHO);
+	ctl->otty.c_cc[VMIN] = 1;	/* read at least 1 char */
+	ctl->otty.c_cc[VTIME] = 0;	/* no timeout */
+	stty(fileno(stderr), &ctl->otty);
 }
 
 /* Come here if a quit signal is received */
 static void onquit(int dummy __attribute__((__unused__)))
 {
 	signal(SIGQUIT, SIG_IGN);
-	if (!inwait) {
+	if (!global_ctl->inwait) {
 		putchar('\n');
-		if (!startup) {
+		if (!global_ctl->startup) {
 			signal(SIGQUIT, onquit);
-			siglongjmp(restore, 1);
+			siglongjmp(global_ctl->restore, 1);
 		} else
-			Pause++;
-	} else if (!dum_opt && notell) {
-		promptlen += fprintf(stderr, _("[Use q or Q to quit]"));
-		notell = 0;
+			global_ctl->Pause = 1;
+	} else if (!global_ctl->dum_opt && global_ctl->notell) {
+		global_ctl->promptlen += fprintf(stderr, _("[Use q or Q to quit]"));
+		global_ctl->notell = 0;
 	}
 	signal(SIGQUIT, onquit);
 }
@@ -1109,12 +1123,12 @@ static void onsusp(int dummy __attribute__((__unused__)))
 
 	/* We're back */
 	signal(SIGTSTP, onsusp);
-	set_tty();
-	if (inwait)
-		siglongjmp(restore, 1);
+	set_tty(global_ctl);
+	if (global_ctl->inwait)
+		siglongjmp(global_ctl->restore, 1);
 }
 
-static void execute(char *filename, char *cmd, ...)
+static void execute(struct more_control *ctl, char *filename, char *cmd, ...)
 {
 	int id;
 	int n;
@@ -1164,101 +1178,101 @@ static void execute(char *filename, char *cmd, ...)
 	if (id > 0) {
 		signal(SIGINT, SIG_IGN);
 		signal(SIGQUIT, SIG_IGN);
-		if (catch_susp)
+		if (ctl->catch_susp)
 			signal(SIGTSTP, SIG_DFL);
 		while (wait(NULL) > 0) ;
 		signal(SIGINT, end_it);
 		signal(SIGQUIT, onquit);
-		if (catch_susp)
+		if (ctl->catch_susp)
 			signal(SIGTSTP, onsusp);
 	} else
 		putserr(_("can't fork\n"));
-	set_tty();
+	set_tty(ctl);
 	puts("------------------------");
-	prompt(filename);
+	prompt(ctl, filename);
 }
 
-static void do_shell(char *filename)
+static void do_shell(struct more_control *ctl, char *filename)
 {
 	char cmdbuf[COMMAND_BUF];
 	int rc;
 	char *expanded;
 
-	kill_line();
+	kill_line(ctl);
 	putchar('!');
 	fflush(stdout);
-	promptlen = 1;
-	if (lastp)
-		putsout(shell_line);
+	ctl->promptlen = 1;
+	if (ctl->lastp)
+		putsout(ctl->shell_line);
 	else {
-		ttyin(cmdbuf, sizeof(cmdbuf) - 2, '!');
+		ttyin(ctl, cmdbuf, sizeof(cmdbuf) - 2, '!');
 		expanded = NULL;
-		rc = expand(&expanded, cmdbuf);
+		rc = expand(ctl, &expanded, cmdbuf);
 		if (expanded) {
-			if (strlen(expanded) < sizeof(shell_line))
-				strcpy(shell_line, expanded);
+			if (strlen(expanded) < sizeof(ctl->shell_line))
+				strcpy(ctl->shell_line, expanded);
 			else
 				rc = -1;
 			free(expanded);
 		}
 		if (rc < 0) {
 			putserr(_("  Overflow\n"));
-			prompt(filename);
+			prompt(ctl, filename);
 			return;
 		} else if (rc > 0) {
-			kill_line();
-			promptlen = printf("!%s", shell_line);
+			kill_line(ctl);
+			ctl->promptlen = printf("!%s", ctl->shell_line);
 		}
 	}
 	fflush(stdout);
 	putcerr('\n');
-	promptlen = 0;
-	shellp = 1;
-	execute(filename, shell, shell, "-c", shell_line, 0);
+	ctl->promptlen = 0;
+	ctl->shellp = 1;
+	execute(ctl, filename, ctl->shell, ctl->shell, "-c", ctl->shell_line, 0);
 }
 
 /* Execute a colon-prefixed command.  Returns <0 if not a command that
  * should cause more of the file to be printed. */
-static int colon(char *filename, int cmd, int nlines)
+static int colon(struct more_control *ctl, char *filename, int cmd, int nlines)
 {
 	if (cmd == 0)
-		ch = readch();
+		ctl->ch = readch(ctl);
 	else
-		ch = cmd;
-	lastcolon = ch;
-	switch (ch) {
+		ctl->ch = cmd;
+	ctl->lastcolon = ctl->ch;
+	switch (ctl->ch) {
 	case 'f':
-		kill_line();
-		if (!no_intty)
-			promptlen =
-			    printf(_("\"%s\" line %d"), fnames[fnum], Currline);
+		kill_line(ctl);
+		if (!ctl->no_intty)
+			ctl->promptlen =
+			    printf(_("\"%s\" line %d"), ctl->fnames[ctl->fnum], ctl->Currline);
 		else
-			promptlen = printf(_("[Not a file] line %d"), Currline);
+			ctl->promptlen = printf(_("[Not a file] line %d"), ctl->Currline);
 		fflush(stdout);
 		return (-1);
 	case 'n':
 		if (nlines == 0) {
-			if (fnum >= nfiles - 1)
+			if (ctl->fnum >= ctl->nfiles - 1)
 				end_it(0);
 			nlines++;
 		}
 		putchar('\r');
-		erasep(0);
-		skipf(nlines);
+		erasep(ctl, 0);
+		skipf(ctl, nlines);
 		return (0);
 	case 'p':
-		if (no_intty) {
+		if (ctl->no_intty) {
 			ringbell();
 			return (-1);
 		}
 		putchar('\r');
-		erasep(0);
+		erasep(ctl, 0);
 		if (nlines == 0)
 			nlines++;
-		skipf(-nlines);
+		skipf(ctl, -nlines);
 		return (0);
 	case '!':
-		do_shell(filename);
+		do_shell(ctl, filename);
 		return (-1);
 	case 'q':
 	case 'Q':
@@ -1270,7 +1284,7 @@ static int colon(char *filename, int cmd, int nlines)
 }
 
 /* Skip n lines in the file f */
-static void skiplns(register int n, register FILE *f)
+static void skiplns(struct more_control *ctl, register int n, register FILE *f)
 {
 	register int c;
 
@@ -1279,47 +1293,47 @@ static void skiplns(register int n, register FILE *f)
 			if (c == EOF)
 				return;
 		n--;
-		Currline++;
+		ctl->Currline++;
 	}
 }
 
 /*  Clear the screen */
-static void doclear(void)
+static void doclear(struct more_control *ctl)
 {
-	if (Clear && !hard) {
-		putstring(Clear);
+	if (ctl->Clear && !ctl->hard) {
+		putp(ctl->Clear);
 		/* Put out carriage return so that system doesn't get
 		 * confused by escape sequences when expanding tabs */
 		putchar('\r');
-		promptlen = 0;
+		ctl->promptlen = 0;
 	}
 }
 
-static void rdline(register FILE *f)
+static void rdline(struct more_control *ctl, register FILE *f)
 {
 	register int c;
 	register char *p;
 
-	prepare_line_buffer();
+	prepare_line_buffer(ctl);
 
-	p = Line;
+	p = ctl->Line;
 	while ((c = Getc(f)) != '\n' && c != EOF
-	       && (size_t)(p - Line) < LineLen - 1)
+	       && (size_t)(p - ctl->Line) < ctl->LineLen - 1)
 		*p++ = c;
 	if (c == '\n')
-		Currline++;
+		ctl->Currline++;
 	*p = '\0';
 }
 
 /* Go to home position */
-static void home(void)
+static void home(struct more_control *ctl)
 {
-	putstring(Home);
+	putp(ctl->Home);
 }
 
 /* Search for nth occurrence of regular expression contained in buf in
  * the file */
-static void search(char buf[], FILE *file, register int n)
+static void search(struct more_control *ctl, char buf[], FILE *file, register int n)
 {
 	long startline = Ftell(file);
 	register long line1 = startline;
@@ -1329,51 +1343,51 @@ static void search(char buf[], FILE *file, register int n)
 	int saveln, rc;
 	regex_t re;
 
-	context.line = saveln = Currline;
-	context.chrctr = startline;
+	ctl->context.line = saveln = ctl->Currline;
+	ctl->context.chrctr = startline;
 	lncount = 0;
 	if (!buf)
 		goto notfound;
 	if ((rc = regcomp(&re, buf, REG_NOSUB)) != 0) {
 		char s[REGERR_BUF];
 		regerror(rc, &re, s, sizeof s);
-		more_error(s);
+		more_error(ctl, s);
 	}
 	while (!feof(file)) {
 		line3 = line2;
 		line2 = line1;
 		line1 = Ftell(file);
-		rdline(file);
+		rdline(ctl, file);
 		lncount++;
-		if (regexec(&re, Line, 0, NULL, 0) == 0) {
+		if (regexec(&re, ctl->Line, 0, NULL, 0) == 0) {
 			if (--n == 0) {
-				if (lncount > 3 || (lncount > 1 && no_intty)) {
+				if (lncount > 3 || (lncount > 1 && ctl->no_intty)) {
 					putchar('\n');
-					if (clreol)
-						cleareol();
+					if (ctl->clreol)
+						cleareol(ctl);
 					putsout(_("...skipping\n"));
 				}
-				if (!no_intty) {
-					Currline -=
+				if (!ctl->no_intty) {
+					ctl->Currline -=
 					    (lncount >= 3 ? 3 : lncount);
 					Fseek(file, line3);
-					if (noscroll) {
-						if (clreol) {
-							home();
-							cleareol();
+					if (ctl->noscroll) {
+						if (ctl->clreol) {
+							home(ctl);
+							cleareol(ctl);
 						} else
-							doclear();
+							doclear(ctl);
 					}
 				} else {
-					kill_line();
-					if (noscroll) {
-						if (clreol) {
-							home();
-							cleareol();
+					kill_line(ctl);
+					if (ctl->noscroll) {
+						if (ctl->clreol) {
+							home(ctl);
+							cleareol(ctl);
 						} else
-							doclear();
+							doclear(ctl);
 					}
-					puts(Line);
+					puts(ctl->Line);
 				}
 				break;
 			}
@@ -1381,17 +1395,17 @@ static void search(char buf[], FILE *file, register int n)
 	}
 	regfree(&re);
 	if (feof(file)) {
-		if (!no_intty) {
-			Currline = saveln;
+		if (!ctl->no_intty) {
+			ctl->Currline = saveln;
 			Fseek(file, startline);
 		} else {
 			putsout(_("\nPattern not found\n"));
 			end_it(0);
 		}
-		free(previousre);
-		previousre = NULL;
+		free(ctl->previousre);
+		ctl->previousre = NULL;
 notfound:
-		more_error(_("Pattern not found"));
+		more_error(ctl, _("Pattern not found"));
 	}
 }
 
@@ -1399,7 +1413,7 @@ notfound:
  * argument followed by the command character.  Return the number of
  * lines to display in the next screenful.  If there is nothing more to
  * display in the current file, zero is returned. */
-static int command(char *filename, register FILE *f)
+static int command(struct more_control *ctl, char *filename, register FILE *f)
 {
 	register int nlines;
 	register int retval = 0;
@@ -1411,30 +1425,30 @@ static int command(char *filename, register FILE *f)
 #define ret(val) retval=val;done++;break
 
 	done = 0;
-	if (!errors)
-		prompt(filename);
+	if (!ctl->errors)
+		prompt(ctl, filename);
 	else
-		errors = 0;
+		ctl->errors = 0;
 	for (;;) {
-		nlines = number(&comchar);
-		lastp = colonch = 0;
+		nlines = number(ctl, &comchar);
+		ctl->lastp = colonch = 0;
 		if (comchar == '.') {	/* Repeat last command */
-			lastp++;
-			comchar = lastcmd;
-			nlines = lastarg;
-			if (lastcmd == ':')
-				colonch = lastcolon;
+			ctl->lastp++;
+			comchar = ctl->lastcmd;
+			nlines = ctl->lastarg;
+			if (ctl->lastcmd == ':')
+				colonch = ctl->lastcolon;
 		}
-		lastcmd = comchar;
-		lastarg = nlines;
-		if ((cc_t) comchar == otty.c_cc[VERASE]) {
-			kill_line();
-			prompt(filename);
+		ctl->lastcmd = comchar;
+		ctl->lastarg = nlines;
+		if ((cc_t) comchar == ctl->otty.c_cc[VERASE]) {
+			kill_line(ctl);
+			prompt(ctl, filename);
 			continue;
 		}
 		switch (comchar) {
 		case ':':
-			retval = colon(filename, colonch, nlines);
+			retval = colon(ctl, filename, colonch, nlines);
 			if (retval >= 0)
 				done++;
 			break;
@@ -1443,7 +1457,7 @@ static int command(char *filename, register FILE *f)
 			{
 				register int initline;
 
-				if (no_intty) {
+				if (ctl->no_intty) {
 					ringbell();
 					return (-1);
 				}
@@ -1452,43 +1466,43 @@ static int command(char *filename, register FILE *f)
 					nlines++;
 
 				putchar('\r');
-				erasep(0);
+				erasep(ctl, 0);
 				putchar('\n');
-				if (clreol)
-					cleareol();
+				if (ctl->clreol)
+					cleareol(ctl);
 				printf(P_("...back %d page",
 					"...back %d pages", nlines),
 					nlines);
-				if (clreol)
-					cleareol();
+				if (ctl->clreol)
+					cleareol(ctl);
 				putchar('\n');
 
-				initline = Currline - dlines * (nlines + 1);
-				if (!noscroll)
+				initline = ctl->Currline - ctl->dlines * (nlines + 1);
+				if (!ctl->noscroll)
 					--initline;
 				if (initline < 0)
 					initline = 0;
 				Fseek(f, 0L);
-				Currline = 0;	/* skiplns() will make Currline correct */
-				skiplns(initline, f);
-				if (!noscroll) {
-					ret(dlines + 1);
+				ctl->Currline = 0;	/* skiplns() will make Currline correct */
+				skiplns(ctl, initline, f);
+				if (!ctl->noscroll) {
+					ret(ctl->dlines + 1);
 				} else {
-					ret(dlines);
+					ret(ctl->dlines);
 				}
 			}
 		case ' ':
 		case 'z':
 			if (nlines == 0)
-				nlines = dlines;
+				nlines = ctl->dlines;
 			else if (comchar == 'z')
-				dlines = nlines;
+				ctl->dlines = nlines;
 			ret(nlines);
 		case 'd':
 		case ctrl('D'):
 			if (nlines != 0)
-				nscroll = nlines;
-			ret(nscroll);
+				ctl->nscroll = nlines;
+			ret(ctl->nscroll);
 		case 'q':
 		case 'Q':
 			end_it(0);
@@ -1498,18 +1512,18 @@ static int command(char *filename, register FILE *f)
 			if (nlines == 0)
 				nlines++;
 			if (comchar == 'f')
-				nlines *= dlines;
+				nlines *= ctl->dlines;
 			putchar('\r');
-			erasep(0);
+			erasep(ctl, 0);
 			putchar('\n');
-			if (clreol)
-				cleareol();
+			if (ctl->clreol)
+				cleareol(ctl);
 			printf(P_("...skipping %d line",
 				"...skipping %d lines", nlines),
 				nlines);
 
-			if (clreol)
-				cleareol();
+			if (ctl->clreol)
+				cleareol(ctl);
 			putchar('\n');
 
 			while (nlines > 0) {
@@ -1519,74 +1533,74 @@ static int command(char *filename, register FILE *f)
 						done++;
 						goto endsw;
 					}
-				Currline++;
+				ctl->Currline++;
 				nlines--;
 			}
-			ret(dlines);
+			ret(ctl->dlines);
 		case '\n':
 			if (nlines != 0)
-				dlines = nlines;
+				ctl->dlines = nlines;
 			else
 				nlines = 1;
 			ret(nlines);
 		case '\f':
-			if (!no_intty) {
-				doclear();
-				Fseek(f, screen_start.chrctr);
-				Currline = screen_start.line;
-				ret(dlines);
+			if (!ctl->no_intty) {
+				doclear(ctl);
+				Fseek(f, ctl->screen_start.chrctr);
+				ctl->Currline = ctl->screen_start.line;
+				ret(ctl->dlines);
 			} else {
 				ringbell();
 				break;
 			}
 		case '\'':
-			if (!no_intty) {
-				kill_line();
+			if (!ctl->no_intty) {
+				kill_line(ctl);
 				putsout(_("\n***Back***\n\n"));
-				Fseek(f, context.chrctr);
-				Currline = context.line;
-				ret(dlines);
+				Fseek(f, ctl->context.chrctr);
+				ctl->Currline = ctl->context.line;
+				ret(ctl->dlines);
 			} else {
 				ringbell();
 				break;
 			}
 		case '=':
-			kill_line();
-			promptlen = printf("%d", Currline);
+			kill_line(ctl);
+			ctl->promptlen = printf("%d", ctl->Currline);
 			fflush(stdout);
 			break;
 		case 'n':
-			if (!previousre) {
-				more_error(_("No previous regular expression"));
+			if (!ctl->previousre) {
+				more_error(ctl, _("No previous regular expression"));
 				break;
 			}
-			lastp++;
+			ctl->lastp++;
 			/* fallthrough */
 		case '/':
 			if (nlines == 0)
 				nlines++;
-			kill_line();
+			kill_line(ctl);
 			putchar('/');
-			promptlen = 1;
+			ctl->promptlen = 1;
 			fflush(stdout);
-			if (lastp) {
+			if (ctl->lastp) {
 				putcerr('\r');
-				search(previousre, f, nlines);
+				search(ctl, ctl->previousre, f, nlines);
 			} else {
-				ttyin(cmdbuf, sizeof(cmdbuf) - 2, '/');
+				ttyin(ctl, cmdbuf, sizeof(cmdbuf) - 2, '/');
 				putcerr('\r');
-				free(previousre);
-				previousre = xstrdup(cmdbuf);
-				search(cmdbuf, f, nlines);
+				free(ctl->previousre);
+				ctl->previousre = xstrdup(cmdbuf);
+				search(ctl, cmdbuf, f, nlines);
 			}
-			ret(dlines - 1);
+			ret(ctl->dlines - 1);
 		case '!':
-			do_shell(filename);
+			do_shell(ctl, filename);
 			break;
 		case '?':
 		case 'h':
-			if (noscroll)
-				doclear();
+			if (ctl->noscroll)
+				doclear(ctl);
 			putsout(_("\n"
 				  "Most commands optionally preceded by integer argument k.  "
 				  "Defaults in brackets.\n"
@@ -1615,16 +1629,16 @@ static int command(char *filename, register FILE *f)
 				 ".                       Repeat previous command\n"));
 			puts("---------------------------------------"
 			     "----------------------------------------");
-			prompt(filename);
+			prompt(ctl, filename);
 			break;
 		case 'v':	/* This case should go right before default */
-			if (!no_intty) {
+			if (!ctl->no_intty) {
 				/* Earlier: call vi +n file. This also
 				 * works for emacs.  POSIX: call vi -c n
 				 * file (when editor is vi or ex). */
 				char *editor, *p;
-				int n = (Currline - dlines <= 0 ? 1 :
-					 Currline - (dlines + 1) / 2);
+				int n = (ctl->Currline - ctl->dlines <= 0 ? 1 :
+					 ctl->Currline - (ctl->dlines + 1) / 2);
 				int split = 0;
 
 				editor = getenv("VISUAL");
@@ -1645,33 +1659,33 @@ static int command(char *filename, register FILE *f)
 					sprintf(cmdbuf, "+%d", n);
 				}
 
-				kill_line();
+				kill_line(ctl);
 				printf("%s %s %s", editor, cmdbuf,
-				       fnames[fnum]);
+				       ctl->fnames[ctl->fnum]);
 				if (split) {
 					cmdbuf[2] = 0;
-					execute(filename, editor, editor,
+					execute(ctl, filename, editor, editor,
 						cmdbuf, cmdbuf + 3,
-						fnames[fnum], (char *)0);
+						ctl->fnames[ctl->fnum], (char *)0);
 				} else
-					execute(filename, editor, editor,
-						cmdbuf, fnames[fnum],
+					execute(ctl, filename, editor, editor,
+						cmdbuf, ctl->fnames[ctl->fnum],
 						(char *)0);
 				break;
 			}
 			/* fallthrough */
 		default:
-			if (dum_opt) {
-				kill_line();
-				if (Senter && Sexit) {
-					putstring(Senter);
-					promptlen =
+			if (ctl->dum_opt) {
+				kill_line(ctl);
+				if (ctl->Senter && ctl->Sexit) {
+					putstring(ctl->Senter);
+					ctl->promptlen =
 					    printf(_
 						   ("[Press 'h' for instructions.]"))
-					    + 2 * soglitch;
-					putstring(Sexit);
+					    + 2 * ctl->soglitch;
+					putstring(ctl->Sexit);
 				} else
-					promptlen =
+					ctl->promptlen =
 					    printf(_
 						   ("[Press 'h' for instructions.]"));
 				fflush(stdout);
@@ -1684,13 +1698,13 @@ static int command(char *filename, register FILE *f)
 	}
 	putchar('\r');
  endsw:
-	inwait = 0;
-	notell++;
+	ctl->inwait = 0;
+	ctl->notell = 1;
 	return (retval);
 }
 
 /* Print out the contents of the file f, one screenful at a time. */
-static void screen(register FILE *f, register int num_lines)
+static void screen(struct more_control *ctl, register FILE *f, register int num_lines)
 {
 	register int c;
 	register int nchars;
@@ -1698,67 +1712,67 @@ static void screen(register FILE *f, register int num_lines)
 	static int prev_len = 1;	/* length of previous line */
 
 	for (;;) {
-		while (num_lines > 0 && !Pause) {
-			if ((nchars = get_line(f, &length)) == EOF) {
-				if (clreol)
-					clreos();
+		while (num_lines > 0 && !ctl->Pause) {
+			if ((nchars = get_line(ctl, f, &length)) == EOF) {
+				if (ctl->clreol)
+					clreos(ctl);
 				return;
 			}
-			if (ssp_opt && length == 0 && prev_len == 0)
+			if (ctl->ssp_opt && length == 0 && prev_len == 0)
 				continue;
 			prev_len = length;
-			if (bad_so
-			    || ((Senter && *Senter == ' ') && (promptlen > 0)))
-				erasep(0);
+			if (ctl->bad_so
+			    || ((ctl->Senter && *ctl->Senter == ' ') && (ctl->promptlen > 0)))
+				erasep(ctl, 0);
 			/* must clear before drawing line since tabs on
 			 * some terminals do not erase what they tab
 			 * over. */
-			if (clreol)
-				cleareol();
-			prbuf(Line, length);
-			if (nchars < promptlen)
-				erasep(nchars);	/* erasep () sets promptlen to 0 */
+			if (ctl->clreol)
+				cleareol(ctl);
+			prbuf(ctl, ctl->Line, length);
+			if (nchars < ctl->promptlen)
+				erasep(ctl, nchars);	/* erasep () sets promptlen to 0 */
 			else
-				promptlen = 0;
+				ctl->promptlen = 0;
 			/* is this needed?
 			 * if (clreol)
 			 *	cleareol();     * must clear again in case we wrapped *
 			 */
-			if (nchars < Mcol || !fold_opt)
-				prbuf("\n", 1);	/* will turn off UL if necessary */
+			if (nchars < ctl->Mcol || !ctl->fold_opt)
+				prbuf(ctl, "\n", 1);	/* will turn off UL if necessary */
 			if (nchars == STOP)
 				break;
 			num_lines--;
 		}
-		if (pstate) {
-			putstring(ULexit);
-			pstate = 0;
+		if (ctl->pstate) {
+			putp(ctl->ULexit);
+			ctl->pstate = 0;
 		}
 		fflush(stdout);
 		if ((c = Getc(f)) == EOF) {
-			if (clreol)
-				clreos();
+			if (ctl->clreol)
+				clreos(ctl);
 			return;
 		}
 
-		if (Pause && clreol)
-			clreos();
+		if (ctl->Pause && ctl->clreol)
+			clreos(ctl);
 		Ungetc(c, f);
-		sigsetjmp(restore, 1);
-		Pause = 0;
-		startup = 0;
-		if ((num_lines = command(NULL, f)) == 0)
+		sigsetjmp(ctl->restore, 1);
+		ctl->Pause = 0;
+		ctl->startup = 0;
+		if ((num_lines = command(ctl, NULL, f)) == 0)
 			return;
-		if (hard && promptlen > 0)
-			erasep(0);
-		if (noscroll && num_lines >= dlines) {
-			if (clreol)
-				home();
+		if (ctl->hard && ctl->promptlen > 0)
+			erasep(ctl, 0);
+		if (ctl->noscroll && num_lines >= ctl->dlines) {
+			if (ctl->clreol)
+				home(ctl);
 			else
-				doclear();
+				doclear(ctl);
 		}
-		screen_start.line = Currline;
-		screen_start.chrctr = Ftell(f);
+		ctl->screen_start.line = ctl->Currline;
+		ctl->screen_start.chrctr = Ftell(f);
 	}
 }
 
@@ -1771,14 +1785,14 @@ static void chgwinsz(int dummy __attribute__((__unused__)))
 	signal(SIGWINCH, SIG_IGN);
 	if (ioctl(fileno(stdout), TIOCGWINSZ, &win) != -1) {
 		if (win.ws_row != 0) {
-			Lpp = win.ws_row;
-			nscroll = Lpp / 2 - 1;
-			if (nscroll <= 0)
-				nscroll = 1;
-			dlines = Lpp - 1;	/* was: Lpp - (noscroll ? 1 : 2) */
+			global_ctl->Lpp = win.ws_row;
+			global_ctl->nscroll = global_ctl->Lpp / 2 - 1;
+			if (global_ctl->nscroll <= 0)
+				global_ctl->nscroll = 1;
+			global_ctl->dlines = global_ctl->Lpp - 1;	/* was: Lpp - (noscroll ? 1 : 2) */
 		}
 		if (win.ws_col != 0)
-			Mcol = win.ws_col;
+			global_ctl->Mcol = win.ws_col;
 	}
 	signal(SIGWINCH, chgwinsz);
 }
@@ -1795,7 +1809,7 @@ static void copy_file(register FILE *f)
 
 
 /*----------------------------- Terminal I/O -------------------------------*/
-static void initterm(void)
+static void initterm(struct more_control *ctl)
 {
 	int ret;
 	char *padstr;
@@ -1807,11 +1821,11 @@ static void initterm(void)
 #endif
 
 #ifndef NON_INTERACTIVE_MORE
-	no_tty = tcgetattr(fileno(stdout), &otty);
+	ctl->no_tty = tcgetattr(fileno(stdout), &ctl->otty);
 #endif
-	if (!no_tty) {
-		docrterase = (otty.c_cc[VERASE] != 255);
-		docrtkill = (otty.c_cc[VKILL] != 255);
+	if (!ctl->no_tty) {
+		ctl->docrterase = (ctl->otty.c_cc[VERASE] != 255);
+		ctl->docrtkill = (ctl->otty.c_cc[VKILL] != 255);
 #ifdef do_SIGTTOU
 		{
 			int tgrp;
@@ -1826,46 +1840,46 @@ static void initterm(void)
 		}
 #endif	/* do_SIGTTOU */
 		if ((term = getenv("TERM")) == NULL) {
-			dumb++;
-			ul_opt = 0;
+			ctl->dumb = 1;
+			ctl->ul_opt = 0;
 		}
 		setupterm(term, 1, &ret);
 		if (ret <= 0) {
-			dumb++;
-			ul_opt = 0;
+			ctl->dumb = 1;
+			ctl->ul_opt = 0;
 		} else {
 #ifdef TIOCGWINSZ
 			if (ioctl(fileno(stdout), TIOCGWINSZ, &win) < 0) {
 #endif
-				Lpp = tigetnum(TERM_LINES);
-				Mcol = tigetnum(TERM_COLS);
+				ctl->Lpp = tigetnum(TERM_LINES);
+				ctl->Mcol = tigetnum(TERM_COLS);
 #ifdef TIOCGWINSZ
 			} else {
-				if ((Lpp = win.ws_row) == 0)
-					Lpp = tigetnum(TERM_LINES);
-				if ((Mcol = win.ws_col) == 0)
-					Mcol = tigetnum(TERM_COLS);
+				if ((ctl->Lpp = win.ws_row) == 0)
+					ctl->Lpp = tigetnum(TERM_LINES);
+				if ((ctl->Mcol = win.ws_col) == 0)
+					ctl->Mcol = tigetnum(TERM_COLS);
 			}
 #endif
-			if ((Lpp <= 0) || tigetflag(TERM_HARD_COPY)) {
-				hard++;	/* Hard copy terminal */
-				Lpp = LINES_PER_PAGE;
+			if ((ctl->Lpp <= 0) || tigetflag(TERM_HARD_COPY)) {
+				ctl->hard = 1;	/* Hard copy terminal */
+				ctl->Lpp = LINES_PER_PAGE;
 			}
 
 			if (tigetflag(TERM_EAT_NEW_LINE))
 				/* Eat newline at last column + 1; dec, concept */
-				eatnl++;
-			if (Mcol <= 0)
-				Mcol = NUM_COLUMNS;
-
-			Wrap = tigetflag(TERM_AUTO_RIGHT_MARGIN);
-			bad_so = tigetflag(TERM_CEOL);
-			eraseln = tigetstr(TERM_CLEAR_TO_LINE_END);
-			Clear = tigetstr(TERM_CLEAR);
-			Senter = tigetstr(TERM_STANDARD_MODE);
-			Sexit = tigetstr(TERM_EXIT_STANDARD_MODE);
-			if ((soglitch = tigetnum(TERM_STD_MODE_GLITCH)) < 0)
-				soglitch = 0;
+				ctl->eatnl++;
+			if (ctl->Mcol <= 0)
+				ctl->Mcol = NUM_COLUMNS;
+
+			ctl->Wrap = tigetflag(TERM_AUTO_RIGHT_MARGIN);
+			ctl->bad_so = tigetflag(TERM_CEOL);
+			ctl->eraseln = tigetstr(TERM_CLEAR_TO_LINE_END);
+			ctl->Clear = tigetstr(TERM_CLEAR);
+			ctl->Senter = tigetstr(TERM_STANDARD_MODE);
+			ctl->Sexit = tigetstr(TERM_EXIT_STANDARD_MODE);
+			if (0 < tigetnum(TERM_STD_MODE_GLITCH))
+				ctl->soglitch = 1;
 
 			/* Set up for underlining:  some terminals don't
 			 * need it; others have start/stop sequences,
@@ -1875,54 +1889,54 @@ static void initterm(void)
 			 * available, settle for standout sequence. */
 			if (tigetflag(TERM_UNDERLINE)
 			    || tigetflag(TERM_OVER_STRIKE))
-				ul_opt = 0;
-			if ((chUL = tigetstr(TERM_UNDERLINE_CHAR)) == NULL)
-				chUL = "";
-			if (((ULenter =
+				ctl->ul_opt = 0;
+			if ((ctl->chUL = tigetstr(TERM_UNDERLINE_CHAR)) == NULL)
+				ctl->chUL = "";
+			if (((ctl->ULenter =
 			      tigetstr(TERM_ENTER_UNDERLINE)) == NULL
-			     || (ULexit =
+			     || (ctl->ULexit =
 				 tigetstr(TERM_EXIT_UNDERLINE)) == NULL)
-			    && !*chUL) {
-				if ((ULenter = Senter) == NULL
-				    || (ULexit = Sexit) == NULL) {
-					ULenter = "";
-					ULexit = "";
+			    && !*ctl->chUL) {
+				if ((ctl->ULenter = ctl->Senter) == NULL
+				    || (ctl->ULexit = ctl->Sexit) == NULL) {
+					ctl->ULenter = "";
+					ctl->ULexit = "";
 				} else
-					ulglitch = soglitch;
+					ctl->ulglitch = ctl->soglitch;
 			} else {
-				ulglitch = 0;
+				ctl->ulglitch = 0;
 			}
 
 			if ((padstr = tigetstr(TERM_PAD_CHAR)) != NULL)
-				PC = *padstr;
-			Home = tigetstr(TERM_HOME);
-			if (Home == NULL || *Home == '\0') {
-				if ((cursorm =
+				ctl->PC = *padstr;
+			ctl->Home = tigetstr(TERM_HOME);
+			if (ctl->Home == NULL || *ctl->Home == '\0') {
+				if ((ctl->cursorm =
 				     tigetstr(TERM_CURSOR_ADDRESS)) != NULL) {
 					const char *t =
-					    (const char *)tparm(cursorm, 0,
+					    (const char *)tparm(ctl->cursorm, 0,
 								   0);
-					xstrncpy(cursorhome, t,
-						 sizeof(cursorhome));
-					Home = cursorhome;
+					xstrncpy(ctl->cursorhome, t,
+						 sizeof(ctl->cursorhome));
+					ctl->Home = ctl->cursorhome;
 				}
 			}
-			EodClr = tigetstr(TERM_CLEAR_TO_SCREEN_END);
-			if ((chBS = tigetstr(TERM_LINE_DOWN)) == NULL)
-				chBS = "\b";
+			ctl->EodClr = tigetstr(TERM_CLEAR_TO_SCREEN_END);
+			if ((ctl->chBS = tigetstr(TERM_LINE_DOWN)) == NULL)
+				ctl->chBS = "\b";
 
 		}
-		if ((shell = getenv("SHELL")) == NULL)
-			shell = "/bin/sh";
+		if ((ctl->shell = getenv("SHELL")) == NULL)
+			ctl->shell = "/bin/sh";
 	}
-	no_intty = tcgetattr(fileno(stdin), &otty);
-	tcgetattr(fileno(stderr), &otty);
-	savetty0 = otty;
-	hardtabs = (otty.c_oflag & TABDLY) != XTABS;
-	if (!no_tty) {
-		otty.c_lflag &= ~(ICANON | ECHO);
-		otty.c_cc[VMIN] = 1;
-		otty.c_cc[VTIME] = 0;
+	ctl->no_intty = tcgetattr(fileno(stdin), &ctl->otty);
+	tcgetattr(fileno(stderr), &ctl->otty);
+	ctl->savetty0 = ctl->otty;
+	ctl->hardtabs = (ctl->otty.c_oflag & TABDLY) != XTABS;
+	if (!ctl->no_tty) {
+		ctl->otty.c_lflag &= ~(ICANON | ECHO);
+		ctl->otty.c_cc[VMIN] = 1;
+		ctl->otty.c_cc[VTIME] = 0;
 	}
 }
 
@@ -1938,6 +1952,20 @@ int main(int argc, char **argv)
 	int clearit = 0;
 	int initline = 0;
 	char *initbuf = NULL;
+	struct more_control ctl = {
+		.firstf = 1,
+		.fold_opt = 1,
+		.notell = 1,
+		.startup = 1,
+		.stop_opt = 1,
+		.ul_opt = 1,
+		.Wrap = 1,
+		.Lpp = LINES_PER_PAGE,
+		.Mcol = NUM_COLUMNS,
+		.nscroll = SCROLL_LEN,
+		0
+	};
+	global_ctl = &ctl;
 
 	setlocale(LC_ALL, "");
 	bindtextdomain(PACKAGE, LOCALEDIR);
@@ -1954,29 +1982,29 @@ int main(int argc, char **argv)
 		}
 	}
 
-	nfiles = argc;
-	fnames = argv;
+	ctl.nfiles = argc;
+	ctl.fnames = argv;
 	setlocale(LC_ALL, "");
-	initterm();
+	initterm(&ctl);
 
 	/* Auto set no scroll on when binary is called page */
 	if (!(strcmp(program_invocation_short_name, "page")))
-		noscroll++;
+		ctl.noscroll++;
 
-	prepare_line_buffer();
+	prepare_line_buffer(&ctl);
 
-	nscroll = Lpp / 2 - 1;
-	if (nscroll <= 0)
-		nscroll = 1;
+	ctl.nscroll = ctl.Lpp / 2 - 1;
+	if (ctl.nscroll <= 0)
+		ctl.nscroll = 1;
 
 	if ((s = getenv("MORE")) != NULL)
-		argscan(s);
+		argscan(&ctl, s);
 
-	while (--nfiles > 0) {
-		if ((chr = (*++fnames)[0]) == '-') {
-			argscan(*fnames + 1);
+	while (--ctl.nfiles > 0) {
+		if ((chr = (*++ctl.fnames)[0]) == '-') {
+			argscan(&ctl, *ctl.fnames + 1);
 		} else if (chr == '+') {
-			s = *fnames;
+			s = *ctl.fnames;
 			if (*++s == '/') {
 				srchopt++;
 				initbuf = xstrdup(s + 1);
@@ -1993,25 +2021,25 @@ int main(int argc, char **argv)
 	}
 	/* allow clreol only if Home and eraseln and EodClr strings are
 	 * defined, and in that case, make sure we are in noscroll mode */
-	if (clreol) {
-		if ((Home == NULL) || (*Home == '\0') ||
-		    (eraseln == NULL) || (*eraseln == '\0') ||
-		    (EodClr == NULL) || (*EodClr == '\0'))
-			clreol = 0;
+	if (ctl.clreol) {
+		if ((ctl.Home == NULL) || (*ctl.Home == '\0') ||
+		    (ctl.eraseln == NULL) || (*ctl.eraseln == '\0') ||
+		    (ctl.EodClr == NULL) || (*ctl.EodClr == '\0'))
+			ctl.clreol = 0;
 		else
-			noscroll = 1;
+			ctl.noscroll = 1;
 	}
-	if (dlines == 0)
-		dlines = Lpp - 1;	/* was: Lpp - (noscroll ? 1 : 2) */
-	left = dlines;
-	if (nfiles > 1)
+	if (ctl.dlines == 0)
+		ctl.dlines = ctl.Lpp - 1;	/* was: Lpp - (noscroll ? 1 : 2) */
+	left = ctl.dlines;
+	if (ctl.nfiles > 1)
 		prnames++;
-	if (!no_intty && nfiles == 0) {
+	if (!ctl.no_intty && ctl.nfiles == 0) {
 		warnx(_("bad usage"));
 		errtryhelp(EXIT_FAILURE);
 	} else
 		f = stdin;
-	if (!no_tty) {
+	if (!ctl.no_tty) {
 		signal(SIGQUIT, onquit);
 		signal(SIGINT, end_it);
 #ifdef SIGWINCH
@@ -2019,106 +2047,106 @@ int main(int argc, char **argv)
 #endif
 		if (signal(SIGTSTP, SIG_IGN) == SIG_DFL) {
 			signal(SIGTSTP, onsusp);
-			catch_susp++;
+			ctl.catch_susp++;
 		}
-		stty(fileno(stderr), &otty);
+		stty(fileno(stderr), &ctl.otty);
 	}
-	if (no_intty) {
-		if (no_tty)
+	if (ctl.no_intty) {
+		if (ctl.no_tty)
 			copy_file(stdin);
 		else {
-			if ((chr = Getc(f)) == '\f')
-				doclear();
+			if ((chr = getc(f)) == '\f')
+				doclear(&ctl);
 			else {
-				Ungetc(chr, f);
-				if (noscroll && (chr != EOF)) {
-					if (clreol)
-						home();
+				ungetc(chr, f);
+				if (ctl.noscroll && (chr != EOF)) {
+					if (ctl.clreol)
+						home(&ctl);
 					else
-						doclear();
+						doclear(&ctl);
 				}
 			}
 			if (srchopt) {
-				free(previousre);
-				previousre = xstrdup(initbuf);
-				search(initbuf, stdin, 1);
-				if (noscroll)
+				free(ctl.previousre);
+				ctl.previousre = xstrdup(initbuf);
+				search(&ctl, initbuf, stdin, 1);
+				if (ctl.noscroll)
 					left--;
 			} else if (initopt)
-				skiplns(initline, stdin);
-			screen(stdin, left);
+				skiplns(&ctl, initline, stdin);
+			screen(&ctl, stdin, left);
 		}
-		no_intty = 0;
+		ctl.no_intty = 0;
 		prnames++;
-		firstf = 0;
+		ctl.firstf = 0;
 	}
 
-	while (fnum < nfiles) {
-		if ((f = checkf(fnames[fnum], &clearit)) != NULL) {
-			context.line = context.chrctr = 0;
-			Currline = 0;
-			if (firstf)
-				sigsetjmp(restore, 1);
-			if (firstf) {
-				firstf = 0;
+	while (ctl.fnum < ctl.nfiles) {
+		if ((f = checkf(&ctl, ctl.fnames[ctl.fnum], &clearit)) != NULL) {
+			ctl.context.line = ctl.context.chrctr = 0;
+			ctl.Currline = 0;
+			if (ctl.firstf)
+				sigsetjmp(ctl.restore, 1);
+			if (ctl.firstf) {
+				ctl.firstf = 0;
 				if (srchopt) {
-					free(previousre);
-					previousre = xstrdup(initbuf);
-					search(initbuf, f, 1);
-					if (noscroll)
+					free(ctl.previousre);
+					ctl.previousre = xstrdup(initbuf);
+					search(&ctl, initbuf, f, 1);
+					if (ctl.noscroll)
 						left--;
 				} else if (initopt)
-					skiplns(initline, f);
-			} else if (fnum < nfiles && !no_tty) {
-				sigsetjmp(restore, 1);
-				left = command(fnames[fnum], f);
+					skiplns(&ctl, initline, f);
+			} else if (ctl.fnum < ctl.nfiles && !ctl.no_tty) {
+				sigsetjmp(ctl.restore, 1);
+				left = command(&ctl, ctl.fnames[ctl.fnum], f);
 			}
 			if (left != 0) {
-				if ((noscroll || clearit)
-				    && (file_size != LONG_MAX)) {
-					if (clreol)
-						home();
+				if ((ctl.noscroll || clearit)
+				    && (ctl.file_size != LONG_MAX)) {
+					if (ctl.clreol)
+						home(&ctl);
 					else
-						doclear();
+						doclear(&ctl);
 				}
 				if (prnames) {
-					if (bad_so)
-						erasep(0);
-					if (clreol)
-						cleareol();
+					if (ctl.bad_so)
+						erasep(&ctl, 0);
+					if (ctl.clreol)
+						cleareol(&ctl);
 					putsout("::::::::::::::");
-					if (promptlen > 14)
-						erasep(14);
+					if (ctl.promptlen > 14)
+						erasep(&ctl, 14);
 					putchar('\n');
-					if (clreol)
-						cleareol();
-					puts(fnames[fnum]);
-					if (clreol)
-						cleareol();
+					if (ctl.clreol)
+						cleareol(&ctl);
+					puts(ctl.fnames[ctl.fnum]);
+					if (ctl.clreol)
+						cleareol(&ctl);
 					puts("::::::::::::::");
-					if (left > Lpp - 4)
-						left = Lpp - 4;
+					if (left > ctl.Lpp - 4)
+						left = ctl.Lpp - 4;
 				}
-				if (no_tty)
+				if (ctl.no_tty)
 					copy_file(f);
 				else {
-					within++;
-					screen(f, left);
-					within = 0;
+					ctl.within = 1;
+					screen(&ctl, f, left);
+					ctl.within = 0;
 				}
 			}
-			sigsetjmp(restore, 1);
+			sigsetjmp(ctl.restore, 1);
 			fflush(stdout);
 			fclose(f);
-			screen_start.line = screen_start.chrctr = 0L;
-			context.line = context.chrctr = 0L;
+			ctl.screen_start.line = ctl.screen_start.chrctr = 0L;
+			ctl.context.line = ctl.context.chrctr = 0L;
 		}
-		fnum++;
-		firstf = 0;
+		ctl.fnum++;
+		ctl.firstf = 0;
 	}
-	free(previousre);
+	free(ctl.previousre);
 	free(initbuf);
-	free(Line);
+	free(ctl.Line);
 	reset_tty();
 	exit(EXIT_SUCCESS);
 }
-- 
2.17.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH 2/2] more: remove global variables, add struct more_control
  2018-05-23 22:24 ` [PATCH 2/2] more: remove global variables, add struct more_control Sami Kerola
@ 2018-05-24  7:10   ` Karel Zak
  2018-05-24 19:27     ` Sami Kerola
  0 siblings, 1 reply; 5+ messages in thread
From: Karel Zak @ 2018-05-24  7:10 UTC (permalink / raw)
  To: Sami Kerola; +Cc: util-linux

On Wed, May 23, 2018 at 11:24:36PM +0100, Sami Kerola wrote:
> This is rather big change, but that is the only way to do this sort job.  To
> keep this change relatively understandable only moves global variables to a
> state structure.
> 
> Signed-off-by: Sami Kerola <kerolasa@iki.fi>
> ---
>  text-utils/more.c | 1316 +++++++++++++++++++++++----------------------
>  1 file changed, 672 insertions(+), 644 deletions(-)
> 
> diff --git a/text-utils/more.c b/text-utils/more.c
> index 603c79003..03aae421f 100644
> --- a/text-utils/more.c
> +++ b/text-utils/more.c
> @@ -85,11 +85,11 @@
>  
>  #define VI	"vi"	/* found on the user's path */
>  
> -#define Fopen(s,m)	(Currline = 0,file_pos=0,fopen(s,m))
> -#define Ftell(f)	file_pos
> -#define Fseek(f,off)	(file_pos=off,fseek(f,off,0))
> -#define Getc(f)		(++file_pos, getc(f))
> -#define Ungetc(c,f)	(--file_pos, ungetc(c,f))
> +#define Fopen(s,m)	(ctl->Currline = 0, ctl->file_pos=0, fopen(s,m))
> +#define Ftell(f)	ctl->file_pos
> +#define Fseek(f,off)	(ctl->file_pos=off, fseek(f, off, 0))
> +#define Getc(f)		(++ctl->file_pos, getc(f))
> +#define Ungetc(c,f)	(--ctl->file_pos, ungetc(c,f))

These macros are horrible. It would be nice to remove it by another
patch and use standard code rather than any macros -- for example
Fopen() is used only once.

For often used stuff like Getc() it would be better to use inline functions.

Anyway, modify 'ctl' (or any global variable) and don't use it as
argument for the macro is horrible.

> -static char *BS = "\b";
> -static char *BSB = "\b \b";
> -static char *CARAT = "^";

#define BS  "\b"
...

> +struct more_control {
> +	struct termios otty;		/* output terminal */
> +	struct termios savetty0;	/* original terminal settings */
> +	long file_pos;			/* file position */
> +	long file_size;			/* file size */
> +	int fnum;			/* argv[] position */
> +	int dlines;			/* screen size in lines */
> +	int nscroll;			/* number of lines scrolled by 'd' */
> +	int promptlen;			/* message prompt length */
> +	int Currline;			/* line we are currently at */
> +	char **fnames;			/* The list of file names */
> +	int nfiles;			/* Number of files left to process */
> +	char *shell;			/* name of the shell to use */
> +	int shellp;			/* does previous shell command exist */
> +	sigjmp_buf restore;		/* siglongjmp() destination */
> +	char *Line;			/* line buffer */
> +	size_t LineLen;			/* size of Line buffer */
> +	int Lpp;			/* lines per page */
> +	char *Clear;			/* clear screen */
> +	char *eraseln;			/* erase line */
> +	char *Senter;			/* enter standout mode */
> +	char *Sexit;			/* exit standout mode */
> +	char *ULenter;			/* enter underline mode */
> +	char *ULexit;			/* exit underline mode */
> +	char *chUL;			/* underline character */
> +	char *chBS;			/* backspace character */
> +	char *Home;			/* go to home */
> +	char *cursorm;			/* cursor movement */
> +	char cursorhome[40];		/* contains cursor movement to home */
> +	char *EodClr;			/* clear rest of screen */
> +	int Mcol;			/* number of columns */
> +	char *previousre;		/* previous search() buf[] item */
> +	struct {
> +		long chrctr;		/* row number */
> +		long line;		/* line number */
> +	} context,
> +	  screen_start;
> +	char ch;
> +	int lastcmd;			/* previous more key command */
> +	int lastarg;			/* previous key command argument */
> +	int lastcolon;			/* is a colon-prefixed key command */
> +	char shell_line[SHELL_LINE];
> +	char PC;			/* pad character */
> +	uint32_t

 Please, 'unsigned int' as on another places.

> +		bad_so:1,		/* true if overwriting does not turn off standout */
> +		catch_susp:1,		/* we should catch the SIGTSTP signal */
> +		clreol:1,		/* do not scroll, paint each screen from the top */
> +		docrterase:1,		/* is erase previous supported */
> +		docrtkill:1,		/* is erase input supported */
> +		dumb:1,			/* is terminal type known */
> +		dum_opt:1,		/* suppress bell */
> +		eatnl:1,		/* is newline ignored after 80 cols */
> +		errors:1,		/* is an error reported */
> +		firstf:1,		/* is the input file the first in list */
> +		fold_opt:1,		/* fold long lines */
> +		hard:1,			/* is this hard copy terminal (a printer or such) */
> +		hardtabs:1,		/* print spaces instead of '\t' */
> +		inwait:1,		/* is waiting user input */
> +		lastp:1,		/* run previous key command */
> +		no_intty:1,		/* is input in interactive mode */
> +		noscroll:1,		/* do not scroll, clear the screen and then display text */
> +		notell:1,		/* suppress quit dialog */
> +		no_tty:1,		/* is output in interactive mode */
> +		Pause:1,		/* is output paused */
> +		pstate:1,		/* current UL state */
> +		soglitch:1,		/* terminal has standout mode glitch */
> +		ssp_opt:1,		/* suppress white space */
> +		startup:1,		/* is startup completed */
> +		stop_opt:1,		/* stop after form feeds */
> +		ulglitch:1,		/* terminal has underline mode glitch */
> +		ul_opt:1,		/* underline as best we can */
> +		within:1,		/* true if we are within a file, false if we are between files */
> +		Wrap:1;			/* set if automargins */
> +};
> +

    Karel

-- 
 Karel Zak  <kzak@redhat.com>
 http://karelzak.blogspot.com

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH 2/2] more: remove global variables, add struct more_control
  2018-05-24  7:10   ` Karel Zak
@ 2018-05-24 19:27     ` Sami Kerola
  2018-05-26  9:32       ` Sami Kerola
  0 siblings, 1 reply; 5+ messages in thread
From: Sami Kerola @ 2018-05-24 19:27 UTC (permalink / raw)
  To: Karel Zak; +Cc: util-linux

On 24 May 2018 at 08:10, Karel Zak <kzak@redhat.com> wrote:
> On Wed, May 23, 2018 at 11:24:36PM +0100, Sami Kerola wrote:
>> -#define Fopen(s,m)   (Currline = 0,file_pos=0,fopen(s,m))
>> -#define Ftell(f)     file_pos
>> -#define Fseek(f,off) (file_pos=off,fseek(f,off,0))
>> -#define Getc(f)              (++file_pos, getc(f))
>> -#define Ungetc(c,f)  (--file_pos, ungetc(c,f))
>> +#define Fopen(s,m)   (ctl->Currline = 0, ctl->file_pos=0, fopen(s,m))
>> +#define Ftell(f)     ctl->file_pos
>> +#define Fseek(f,off) (ctl->file_pos=off, fseek(f, off, 0))
>> +#define Getc(f)              (++ctl->file_pos, getc(f))
>> +#define Ungetc(c,f)  (--ctl->file_pos, ungetc(c,f))
>
> These macros are horrible. It would be nice to remove it by another
> patch and use standard code rather than any macros -- for example
> Fopen() is used only once.
>
> For often used stuff like Getc() it would be better to use inline functions.
>
> Anyway, modify 'ctl' (or any global variable) and don't use it as
> argument for the macro is horrible.

My intention is to get rid of these macros completely. Precarious macros
with pointer arguments will relatively soon. As it sounds you probably
want that change to be added to this series. I'll do that during weekend.

I assume you already figured these more(1) changes are related to a
change set I submitted couple years go, but what was not merged.
Basically haven't lost hope with more(1), this pager can and should
be modernised. But I did learn from previous experience that that it
is no good to send too large change set. That is why this comes in
small(ish) bits. Unfortunately first few changes will be quite sweeping.
For example most if not all variable names need renaming to make
the code understandable. When these big changes are done things
like sane signal handling (without relying on longjmp()) is in todo
list among with many other things.

>> -static char *BS = "\b";
>> -static char *BSB = "\b \b";
>> -static char *CARAT = "^";
>
> #define BS  "\b"

Ack.

>> +struct more_control {
>> +     struct termios otty;            /* output terminal */
>> +     struct termios savetty0;        /* original terminal settings */
>> +     long file_pos;                  /* file position */
>> +     long file_size;                 /* file size */
>> +     int fnum;                       /* argv[] position */
>> +     int dlines;                     /* screen size in lines */
>> +     int nscroll;                    /* number of lines scrolled by 'd' */
>> +     int promptlen;                  /* message prompt length */
>> +     int Currline;                   /* line we are currently at */
>> +     char **fnames;                  /* The list of file names */
>> +     int nfiles;                     /* Number of files left to process */
>> +     char *shell;                    /* name of the shell to use */
>> +     int shellp;                     /* does previous shell command exist */
>> +     sigjmp_buf restore;             /* siglongjmp() destination */
>> +     char *Line;                     /* line buffer */
>> +     size_t LineLen;                 /* size of Line buffer */
>> +     int Lpp;                        /* lines per page */
>> +     char *Clear;                    /* clear screen */
>> +     char *eraseln;                  /* erase line */
>> +     char *Senter;                   /* enter standout mode */
>> +     char *Sexit;                    /* exit standout mode */
>> +     char *ULenter;                  /* enter underline mode */
>> +     char *ULexit;                   /* exit underline mode */
>> +     char *chUL;                     /* underline character */
>> +     char *chBS;                     /* backspace character */
>> +     char *Home;                     /* go to home */
>> +     char *cursorm;                  /* cursor movement */
>> +     char cursorhome[40];            /* contains cursor movement to home */
>> +     char *EodClr;                   /* clear rest of screen */
>> +     int Mcol;                       /* number of columns */
>> +     char *previousre;               /* previous search() buf[] item */
>> +     struct {
>> +             long chrctr;            /* row number */
>> +             long line;              /* line number */
>> +     } context,
>> +       screen_start;
>> +     char ch;
>> +     int lastcmd;                    /* previous more key command */
>> +     int lastarg;                    /* previous key command argument */
>> +     int lastcolon;                  /* is a colon-prefixed key command */
>> +     char shell_line[SHELL_LINE];
>> +     char PC;                        /* pad character */
>> +     uint32_t
>
>  Please, 'unsigned int' as on another places.

Ack.

-- 
Sami Kerola
http://www.iki.fi/kerolasa/

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH 2/2] more: remove global variables, add struct more_control
  2018-05-24 19:27     ` Sami Kerola
@ 2018-05-26  9:32       ` Sami Kerola
  0 siblings, 0 replies; 5+ messages in thread
From: Sami Kerola @ 2018-05-26  9:32 UTC (permalink / raw)
  To: Karel Zak; +Cc: util-linux

On Thu, 24 May 2018, Sami Kerola wrote:

> On 24 May 2018 at 08:10, Karel Zak <kzak@redhat.com> wrote:
> > On Wed, May 23, 2018 at 11:24:36PM +0100, Sami Kerola wrote:
> >> -#define Fopen(s,m)   (Currline = 0,file_pos=0,fopen(s,m))
> >> -#define Ftell(f)     file_pos
> >> -#define Fseek(f,off) (file_pos=off,fseek(f,off,0))
> >> -#define Getc(f)              (++file_pos, getc(f))
> >> -#define Ungetc(c,f)  (--file_pos, ungetc(c,f))
> >> +#define Fopen(s,m)   (ctl->Currline = 0, ctl->file_pos=0, fopen(s,m))
> >> +#define Ftell(f)     ctl->file_pos
> >> +#define Fseek(f,off) (ctl->file_pos=off, fseek(f, off, 0))
> >> +#define Getc(f)              (++ctl->file_pos, getc(f))
> >> +#define Ungetc(c,f)  (--ctl->file_pos, ungetc(c,f))
> >
> > These macros are horrible. It would be nice to remove it by another
> > patch and use standard code rather than any macros -- for example
> > Fopen() is used only once.
> >
> > For often used stuff like Getc() it would be better to use inline functions.
> >
> > Anyway, modify 'ctl' (or any global variable) and don't use it as
> > argument for the macro is horrible.
> 
> My intention is to get rid of these macros completely. Precarious macros
> with pointer arguments will relatively soon. As it sounds you probably
> want that change to be added to this series. I'll do that during weekend.

Done in commit 7844bd1 that is available from my repo.

The 'more' branch also fixes BSB, BS, and CARAT definitions, and control 
structure uint32_t to unsigned int, see commit c02140b.

https://github.com/kerolasa/util-linux/commits/more

----------------------------------------------------------------
The following changes since commit 3abbd0814cf479f709a2da5822a215db69c5a6d0:
  libblkid: (ntfs) fix cluster size check (2018-05-25 21:02:23 +0200)
are available in the Git repository at:
  git://github.com/kerolasa/util-linux.git more 
for you to fetch changes up to 7844bd13df52dcf7afd44f43b1daa8ae506ddb11:
  more: remove function like preprocessor defines (2018-05-26 10:21:00 +0100)
----------------------------------------------------------------
Sami Kerola (3):
      more: move couple functions
      more: remove global variables, add struct more_control
      more: remove function like preprocessor defines

 text-utils/more.c | 1674 ++++++++++++++++++++++++++++++++++++++++-------------------------------------
 1 file changed, 868 insertions(+), 806 deletions(-)

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2018-05-26  9:32 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-05-23 22:24 [PATCH 1/2] more: move couple functions Sami Kerola
2018-05-23 22:24 ` [PATCH 2/2] more: remove global variables, add struct more_control Sami Kerola
2018-05-24  7:10   ` Karel Zak
2018-05-24 19:27     ` Sami Kerola
2018-05-26  9:32       ` Sami Kerola

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).