// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Copyright (C) 1996-2005 Paul Mackerras.
 */
#include <linux/string.h>
#include <asm/udbg.h>
#include <asm/time.h>
#include "nonstdio.h"

static bool paginating, paginate_skipping;
static unsigned long paginate_lpp; /* Lines Per Page */
static unsigned long paginate_pos;

void xmon_start_pagination(void)
{
	paginating = true;
	paginate_skipping = false;
	paginate_pos = 0;
}

void xmon_end_pagination(void)
{
	paginating = false;
}

void xmon_set_pagination_lpp(unsigned long lpp)
{
	paginate_lpp = lpp;
}

static int xmon_readchar(void)
{
	if (udbg_getc)
		return udbg_getc();
	return -1;
}

static int xmon_write(const char *ptr, int nb)
{
	int rv = 0;
	const char *p = ptr, *q;
	const char msg[] = "[Hit a key (a:all, q:truncate, any:next page)]";

	if (nb <= 0)
		return rv;

	if (paginating && paginate_skipping)
		return nb;

	if (paginate_lpp) {
		while (paginating && (q = strchr(p, '\n'))) {
			rv += udbg_write(p, q - p + 1);
			p = q + 1;
			paginate_pos++;

			if (paginate_pos >= paginate_lpp) {
				udbg_write(msg, strlen(msg));

				switch (xmon_readchar()) {
				case 'a':
					paginating = false;
					break;
				case 'q':
					paginate_skipping = true;
					break;
				default:
					/* nothing */
					break;
				}

				paginate_pos = 0;
				udbg_write("\r\n", 2);

				if (paginate_skipping)
					return nb;
			}
		}
	}

	return rv + udbg_write(p, nb - (p - ptr));
}

int xmon_putchar(int c)
{
	char ch = c;

	if (c == '\n')
		xmon_putchar('\r');
	return xmon_write(&ch, 1) == 1? c: -1;
}

static char line[256];
static char *lineptr;
static int lineleft;

static int xmon_getchar(void)
{
	int c;

	if (lineleft == 0) {
		lineptr = line;
		for (;;) {
			c = xmon_readchar();
			if (c == -1 || c == 4)
				break;
			if (c == '\r' || c == '\n') {
				*lineptr++ = '\n';
				xmon_putchar('\n');
				break;
			}
			switch (c) {
			case 0177:
			case '\b':
				if (lineptr > line) {
					xmon_putchar('\b');
					xmon_putchar(' ');
					xmon_putchar('\b');
					--lineptr;
				}
				break;
			case 'U' & 0x1F:
				while (lineptr > line) {
					xmon_putchar('\b');
					xmon_putchar(' ');
					xmon_putchar('\b');
					--lineptr;
				}
				break;
			default:
				if (lineptr >= &line[sizeof(line) - 1])
					xmon_putchar('\a');
				else {
					xmon_putchar(c);
					*lineptr++ = c;
				}
			}
		}
		lineleft = lineptr - line;
		lineptr = line;
	}
	if (lineleft == 0)
		return -1;
	--lineleft;
	return *lineptr++;
}

char *xmon_gets(char *str, int nb)
{
	char *p;
	int c;

	for (p = str; p < str + nb - 1; ) {
		c = xmon_getchar();
		if (c == -1) {
			if (p == str)
				return NULL;
			break;
		}
		*p++ = c;
		if (c == '\n')
			break;
	}
	*p = 0;
	return str;
}

void xmon_printf(const char *format, ...)
{
	va_list args;
	static char xmon_outbuf[1024];
	int rc, n;

	va_start(args, format);
	n = vsnprintf(xmon_outbuf, sizeof(xmon_outbuf), format, args);
	va_end(args);

	rc = xmon_write(xmon_outbuf, n);

	if (n && rc == 0) {
		/* No udbg hooks, fallback to printk() - dangerous */
		pr_cont("%s", xmon_outbuf);
	}
}

void xmon_puts(const char *str)
{
	xmon_write(str, strlen(str));
}
