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>
14 #include <lunaix/process.h>
15 #include <lunaix/spike.h>
18 raise_sig(struct term* at_term, struct linebuffer* lbuf, int sig)
20 term_sendsig(at_term, sig);
21 lbuf->sflags |= LSTATE_SIGRAISE;
24 static inline int must_inline optimize("-fipa-cp-clone")
25 lcntl_transform_seq(struct term* tdev, struct linebuffer* lbuf, bool out)
27 struct rbuffer* raw = lbuf->current;
28 struct rbuffer* cooked = lbuf->next;
29 struct rbuffer* output = tdev->line_out.current;
31 int i = 0, _if = tdev->iflags & -!out, _of = tdev->oflags & -!!out,
33 int allow_more = 1, latest_eol = cooked->ptr;
36 int (*lcntl_slave_put)(struct term*, struct linebuffer*, char) =
37 tdev->lcntl->process_and_put;
39 #define EOL tdev->cc[_VEOL]
40 #define EOF tdev->cc[_VEOF]
41 #define ERASE tdev->cc[_VERASE]
42 #define KILL tdev->cc[_VKILL]
43 #define INTR tdev->cc[_VINTR]
44 #define QUIT tdev->cc[_VQUIT]
45 #define SUSP tdev->cc[_VSUSP]
47 #define putc_safe(rb, chr) \
49 if (!rbuffer_put_nof(rb, chr)) { \
55 // Keep all cc's (except VMIN & VTIME) up to L2 cache.
56 for (size_t i = 0; i < _VMIN; i++) {
57 prefetch_rd(&tdev->cc[i], 2);
61 while (allow_more && rbuffer_get(raw, &c)) {
63 if (c == '\r' && ((_if & _ICRNL) || (_of & _OCRNL))) {
65 } else if (c == '\n') {
66 if ((_if & _INLCR) || (_of & (_ONLRET))) {
72 if ((_if & _IGNBRK)) {
76 if ((_if & _BRKINT)) {
77 raise_sig(tdev, lbuf, SIGINT);
82 if ('a' <= c && c <= 'z') {
85 } else if ((_of & _OLCUC)) {
95 latest_eol = cooked->ptr + 1;
96 if ((_lf & _ECHONL)) {
97 rbuffer_put(output, c);
101 // For input procesing
103 if (c == '\n' || c == EOL) {
104 lbuf->sflags |= LSTATE_EOL;
105 } else if (c == EOF) {
106 lbuf->sflags |= LSTATE_EOF;
109 } else if (c == INTR) {
110 raise_sig(tdev, lbuf, SIGINT);
111 } else if (c == QUIT) {
112 raise_sig(tdev, lbuf, SIGKILL);
114 } else if (c == SUSP) {
115 raise_sig(tdev, lbuf, SIGSTOP);
116 } else if (c == ERASE) {
117 if (!rbuffer_erase(cooked))
119 } else if (c == KILL) {
120 // TODO shrink the rbuffer
125 if ((_lf & _ECHOE) && c == ERASE) {
126 rbuffer_put(output, '\x8');
127 rbuffer_put(output, ' ');
128 rbuffer_put(output, '\x8');
130 if ((_lf & _ECHOK) && c == KILL) {
131 rbuffer_put(output, c);
132 rbuffer_put(output, '\n');
139 rbuffer_put(output, c);
145 if (c == '\n' && (_of & _ONLCR)) {
146 putc_safe(cooked, '\r');
150 if (!out && (_lf & _IEXTEN) && lcntl_slave_put) {
151 allow_more = lcntl_slave_put(tdev, lbuf, c);
153 allow_more = rbuffer_put_nof(cooked, c);
157 if (!out && !rbuffer_empty(output) && !(_lf & _NOFLSH)) {
167 lcntl_transform_inseq(struct term* tdev)
169 return lcntl_transform_seq(tdev, &tdev->line_in, false);
173 lcntl_transform_outseq(struct term* tdev)
175 return lcntl_transform_seq(tdev, &tdev->line_out, true);