3 * @author Lunaixsky (lunaxisky@qq.com)
4 * @brief Line controller master that handle all POSIX-control code
8 * @copyright Copyright (c) 2023
12 #include <usr/lunaix/term.h>
16 #include <lunaix/process.h>
17 #include <lunaix/spike.h>
20 init_lcntl_state(struct lcntl_state* state,
21 struct term* tdev, enum lcntl_dir direction)
23 *state = (struct lcntl_state) {
27 .direction = direction,
28 .echobuf = tdev->line_out.current,
31 struct linebuffer* lb;
32 if (direction == INBOUND) {
33 state->_if = tdev->iflags;
37 state->_of = tdev->oflags;
41 state->inbuf = lb->current;
42 state->outbuf = lb->next;
43 state->active_line = lb;
47 raise_sig(struct lcntl_state* state, int sig)
49 term_sendsig(state->tdev, sig);
50 lcntl_raise_line_event(state, LEVT_SIGRAISE);
54 __remap_character(struct lcntl_state* state, char c)
57 if ((state->_if & _ICRNL) || (state->_of & _OCRNL)) {
62 if ((state->_if & _INLCR) || (state->_of & (_ONLRET))) {
66 else if ('a' <= c && c <= 'z') {
67 if ((state->_if & _IUCLC)) {
69 } else if ((state->_of & _OLCUC)) {
78 lcntl_echo_char(struct lcntl_state* state, char c)
80 rbuffer_put(state->echobuf, c);
84 __ansi_actcontrol(struct lcntl_state* state, char chr);
86 static inline int must_inline
87 lcntl_transform_seq(struct lcntl_state* state)
89 struct term* tdev = state->tdev;
94 #define EOL tdev->cc[_VEOL]
95 #define EOF tdev->cc[_VEOF]
96 #define ERASE tdev->cc[_VERASE]
97 #define KILL tdev->cc[_VKILL]
98 #define INTR tdev->cc[_VINTR]
99 #define QUIT tdev->cc[_VQUIT]
100 #define SUSP tdev->cc[_VSUSP]
102 while (!lcntl_test_flag(state, LCNTLF_STOP))
104 lcntl_unset_flag(state, LCNTLF_SPECIAL_CHAR);
106 if (!rbuffer_get(state->inbuf, &c)) {
110 c = __remap_character(state, c);
113 if ((state->_if & _IGNBRK)) {
117 if ((state->_if & _BRKINT)) {
118 raise_sig(state, SIGINT);
123 if (lcntl_outbound(state)) {
128 if (lcntl_check_echo(state, _ECHONL)) {
129 lcntl_echo_char(state, c);
133 // For input procesing
135 lcntl_set_flag(state, LCNTLF_SPECIAL_CHAR);
137 if (c == '\n' || c == EOL) {
138 lcntl_raise_line_event(state, LEVT_EOL);
141 lcntl_raise_line_event(state, LEVT_EOF);
142 lcntl_set_flag(state, LCNTLF_CLEAR_INBUF);
143 lcntl_set_flag(state, LCNTLF_STOP);
145 else if (c == INTR) {
146 raise_sig(state, SIGINT);
147 lcntl_set_flag(state, LCNTLF_CLEAR_OUTBUF);
149 else if (c == QUIT) {
150 raise_sig(state, SIGKILL);
151 lcntl_set_flag(state, LCNTLF_CLEAR_OUTBUF);
152 lcntl_set_flag(state, LCNTLF_STOP);
154 else if (c == SUSP) {
155 raise_sig(state, SIGSTOP);
157 else if (c == ERASE) {
158 if (rbuffer_erase(state->outbuf) &&
159 lcntl_check_echo(state, _ECHOE))
161 lcntl_echo_char(state, '\x8');
162 lcntl_echo_char(state, ' ');
163 lcntl_echo_char(state, '\x8');
167 else if (c == KILL) {
168 lcntl_set_flag(state, LCNTLF_CLEAR_OUTBUF);
171 lcntl_unset_flag(state, LCNTLF_SPECIAL_CHAR);
174 if (lcntl_check_echo(state, _ECHOK) && c == KILL) {
175 lcntl_echo_char(state, c);
176 lcntl_echo_char(state, '\n');
180 if (c == '\n' && (state->_of & _ONLCR)) {
181 full = !rbuffer_put_nof(state->outbuf, '\r');
185 if (lcntl_inbound(state) && (state->_lf & _IEXTEN)) {
186 full = !__ansi_actcontrol(state, c);
189 full = !lcntl_put_char(state, c);
193 if (lcntl_test_flag(state, LCNTLF_CLEAR_INBUF)) {
194 rbuffer_clear(state->inbuf);
195 lcntl_unset_flag(state, LCNTLF_CLEAR_INBUF);
198 if (lcntl_test_flag(state, LCNTLF_CLEAR_OUTBUF)) {
199 rbuffer_clear(state->outbuf);
200 lcntl_unset_flag(state, LCNTLF_CLEAR_OUTBUF);
206 if (state->direction != OUTBOUND && !(state->_lf & _NOFLSH)) {
210 line_flip(state->active_line);
216 lcntl_transform_inseq(struct term* tdev)
218 struct lcntl_state state;
220 init_lcntl_state(&state, tdev, INBOUND);
221 return lcntl_transform_seq(&state);
225 lcntl_transform_outseq(struct term* tdev)
227 struct lcntl_state state;
229 init_lcntl_state(&state, tdev, OUTBOUND);
230 return lcntl_transform_seq(&state);
234 lcntl_put_char(struct lcntl_state* state, char c)
236 if (lcntl_check_echo(state, _ECHO)) {
237 lcntl_echo_char(state, c);
240 if (!lcntl_test_flag(state, LCNTLF_SPECIAL_CHAR)) {
241 return rbuffer_put_nof(state->outbuf, c);