|
|
1.1 root 1: //
2: // nono
3: // Copyright (C) 2020 [email protected]
4: //
5:
6: #include "console.h"
7: #include "mystring.h"
8: #include <poll.h>
9:
10: //
11: // コンソール基本クラス
12: //
13:
14: // コンストラクタ
15: Console::Console()
16: {
17: inp.fd = -1;
18: inp.file = NULL;
19: out.fd = -1;
20: out.file = NULL;
21: }
22:
23: #if defined(HAVE_HISTEDIT_H)
24: // プロンプト文字列を返す (editline からコールバックで呼ばれる)
25: static char *
26: prompt_callback(EditLine *e)
27: {
28: void *p;
29:
30: // CLIENTDATA に (char *)prompt が入っている
31: el_get(e, EL_CLIENTDATA, &p);
32: return (char *)p;
33: }
34: #endif
35:
36: // EditLine を初期化する。p はプロンプト文字列。
37: void
38: Console::InitEditLine(const char *prompt_arg)
39: {
40: // editline(3) を使わない場合は、プロンプトを自前で出すために覚えておく。
41: // 使う場合には代入が無駄になるけど気にしない。
42: prompt = prompt_arg;
43:
44: #if defined(HAVE_HISTEDIT_H)
45: if (use_editline) {
46: // ヒストリの初期化
47: hist = history_init();
48: history(hist, &hev, H_SETSIZE, 100);
49:
50: // editline の初期化、設定
51: el = el_init(getprogname(), inp.file, out.file, stderr);
52: if (el == NULL) {
53: // どうすべ
54: warnx("el_init failed");
55: return;
56: }
57: // CLIENTDATA にプロンプトを入れておく
58: el_set(el, EL_CLIENTDATA, prompt_arg);
59: el_set(el, EL_PROMPT, prompt_callback);
60: el_set(el, EL_EDITOR, "emacs");
61: el_set(el, EL_HIST, history, hist);
62: }
63: #endif
64: }
65:
66: // クローズ
67: void
68: Console::Close()
69: {
70: #if defined(HAVE_HISTEDIT_H)
71: if (use_editline) {
72: el_end(el);
73: }
74: #endif
75:
76: // fclose は fd も閉じる。
77: if (inp.file != NULL) {
78: fclose(inp.file);
79: inp.file = NULL;
80: inp.fd = -1;
81: }
82: if (out.file != NULL) {
83: fclose(out.file);
84: out.file = NULL;
85: out.fd = -1;
86: }
87: }
88:
89: // プロンプトを出力する
90: void
91: Console::Prompt()
92: {
93: #if defined(HAVE_HISTEDIT_H)
94: if (use_editline) {
95: // editline(3) を使う場合は Gets() がプロンプトを出すので
96: // ここでは何もしない。
97: } else
98: #endif
99: {
100: // そうでない場合は、ここで自前でプロンプトを出す。
101: Print("%s", prompt);
102: Flush();
103: }
104: }
105:
106: // 出力
107: void
108: Console::Print(const char *fmt, ...)
109: {
110: va_list ap;
111:
112: va_start(ap, fmt);
113: vfprintf(out.file, fmt, ap);
114: va_end(ap);
115: }
116:
117: // 出力フラッシュ
118: void
119: Console::Flush()
120: {
121: fflush(out.file);
122: }
123:
124: // 1行出力
125: bool
126: Console::Gets(std::string& buf)
127: {
128: #if defined(HAVE_HISTEDIT_H)
129: if (use_editline)
130: return Gets_editline(buf);
131: else
132: #endif
133: return Gets_normal(buf);
134: }
135:
136: #if defined(HAVE_HISTEDIT_H)
137: // 1行出力 (Editline 版)
138: bool
139: Console::Gets_editline(std::string& buf)
140: {
141: const char *p;
142: int num;
143:
144: p = el_gets(el, &num);
145: if (p == NULL || num < 1) {
146: // EOF
147: return false;
148: }
149: // 呼び出し元へは EditLine から入力されたものをそのまま返す
150: buf = std::string(p);
151:
152: // ヒストリに記録
153: // の前に前後の空白は取り除いておく
154: std::string hbuf = string_ltrim(buf);
155: string_rtrim(hbuf);
156:
157: // 空文字列でなければ、ヒストリに記録
158: if (!hbuf.empty()) {
159: history(hist, &hev, H_ENTER, hbuf.c_str());
160: }
161:
162: return true;
163: }
164: #endif
165:
166: // 1行出力 (通常版)
167: bool
168: Console::Gets_normal(std::string& buf)
169: {
170: char cbuf[1024];
171:
172: if (fgets(cbuf, sizeof(cbuf), inp.file) == NULL) {
173: return false;
174: }
175: buf = std::string(cbuf);
176: return true;
177: }
178:
179: // 入力チェック
180: int
181: Console::Poll()
182: {
183: struct pollfd pfd;
184:
185: if (inp.fd == -1) {
186: errno = EBADF;
187: return -1;
188: }
189:
190: pfd.fd = inp.fd;
191: pfd.events = POLLIN;
192: pfd.revents = 0;
193: int r = poll(&pfd, 1, 0);
194: return r;
195: }
196:
197: // ファイルディスクリプタから FILE* を開く
198: void
199: Console::FDOpen()
200: {
201: inp.file = fdopen(inp.fd, "r");
202: out.file = fdopen(out.fd, "w");
203: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.