File:  [Isaki's NoNo m68k/m88k emulator] / nono / debugger / console.cpp
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs
Wed Apr 29 17:04:56 2026 UTC (2 months, 3 weeks ago) by root
Branches: MAIN, Isaki
CVS tags: v014, v013, v012, HEAD
nono 0.2.1

//
// nono
// Copyright (C) 2020 nono project
// Licensed under nono-license.txt
//

#include "console.h"
#include "mystring.h"
#include <poll.h>

//
// コンソール基本クラス
//

// コンストラクタ
Console::Console()
{
	inp.fd = -1;
	inp.file = NULL;
	out.fd = -1;
	out.file = NULL;
}

#if defined(HAVE_HISTEDIT_H)
// プロンプト文字列を返す (editline からコールバックで呼ばれる)
static char *
prompt_callback(EditLine *e)
{
	void *p;

	// CLIENTDATA に (char *)prompt が入っている
	el_get(e, EL_CLIENTDATA, &p);
	return (char *)p;
}
#endif

// EditLine を初期化する。p はプロンプト文字列。
void
Console::InitEditLine(const char *prompt_arg)
{
	// editline(3) を使わない場合は、プロンプトを自前で出すために覚えておく。
	// 使う場合には代入が無駄になるけど気にしない。
	prompt = prompt_arg;

#if defined(HAVE_HISTEDIT_H)
	if (use_editline) {
		// ヒストリの初期化
		hist = history_init();
		history(hist, &hev, H_SETSIZE, 100);

		// editline の初期化、設定
		el = el_init(getprogname(), inp.file, out.file, stderr);
		if (el == NULL) {
			// どうすべ
			warnx("el_init failed");
			return;
		}
		// CLIENTDATA にプロンプトを入れておく
		el_set(el, EL_CLIENTDATA, prompt_arg);
		el_set(el, EL_PROMPT, prompt_callback);
		el_set(el, EL_EDITOR, "emacs");
		el_set(el, EL_HIST, history, hist);
	}
#endif
}

// クローズ
void
Console::Close()
{
#if defined(HAVE_HISTEDIT_H)
	if (use_editline) {
		el_end(el);
	}
#endif

	// fclose は fd も閉じる。
	if (inp.file != NULL) {
		fclose(inp.file);
		inp.file = NULL;
		inp.fd = -1;
	}
	if (out.file != NULL) {
		fclose(out.file);
		out.file = NULL;
		out.fd = -1;
	}
}

// プロンプトを出力する
void
Console::Prompt()
{
#if defined(HAVE_HISTEDIT_H)
	if (use_editline) {
		// editline(3) を使う場合は Gets() がプロンプトを出すので
		// ここでは何もしない。
	} else
#endif
	{
		// そうでない場合は、ここで自前でプロンプトを出す。
		Print("%s", prompt);
		Flush();
	}
}

// 出力
void
Console::Print(const char *fmt, ...)
{
	va_list ap;

	va_start(ap, fmt);
	vfprintf(out.file, fmt, ap);
	va_end(ap);
}

// 出力フラッシュ
void
Console::Flush()
{
	fflush(out.file);
}

// 1行出力
bool
Console::Gets(std::string& buf)
{
#if defined(HAVE_HISTEDIT_H)
	if (use_editline)
		return Gets_editline(buf);
	else
#endif
		return Gets_normal(buf);
}

#if defined(HAVE_HISTEDIT_H)
// 1行出力 (Editline 版)
bool
Console::Gets_editline(std::string& buf)
{
	const char *p;
	int num;

	p = el_gets(el, &num);
	if (p == NULL || num < 1) {
		// EOF
		return false;
	}
	// 呼び出し元へは EditLine から入力されたものをそのまま返す
	buf = std::string(p);

	// ヒストリに記録
	// の前に前後の空白は取り除いておく
	std::string hbuf = string_trim(buf);

	// 空文字列でなければ、ヒストリに記録
	if (!hbuf.empty()) {
		history(hist, &hev, H_ENTER, hbuf.c_str());
	}

	return true;
}
#endif

// 1行出力 (通常版)
bool
Console::Gets_normal(std::string& buf)
{
	char cbuf[1024];

	if (fgets(cbuf, sizeof(cbuf), inp.file) == NULL) {
		return false;
	}
	buf = std::string(cbuf);
	return true;
}

// 入力チェック
int
Console::Poll(int msec)
{
	struct pollfd pfd;

	if (inp.fd == -1) {
		errno = EBADF;
		return -1;
	}

	pfd.fd = inp.fd;
	pfd.events = POLLIN;
	pfd.revents = 0;
	int r = poll(&pfd, 1, msec);
	return r;
}

// ファイルディスクリプタから FILE* を開く
void
Console::FDOpen()
{
	inp.file = fdopen(inp.fd, "r");
	out.file = fdopen(out.fd, "w");
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.