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, SIGINT);
21 lbuf->sflags |= LSTATE_SIGRAISE;
25 lcntl_invoke_slaves(struct term* tdev, struct linebuffer* lbuf, char c)
28 struct term_lcntl *lcntl, *n;
29 llist_for_each(lcntl, n, &tdev->lcntl_stack, lcntls)
31 allow_more = lcntl->process_and_put(tdev, lbuf, c);
42 static inline int optimize("ipa-cp-clone")
43 lcntl_transform_seq(struct term* tdev, struct linebuffer* lbuf, bool out)
45 struct rbuffer* raw = lbuf->current;
46 struct rbuffer* cooked = lbuf->next;
47 struct rbuffer* output = tdev->line_out.current;
49 int i = 0, _if = tdev->iflags & -!out, _of = tdev->oflags & -!!out,
51 int allow_more = 1, latest_eol = cooked->ptr;
53 bool should_flush = false;
55 #define EOL tdev->cc[_VEOL]
56 #define EOF tdev->cc[_VEOF]
57 #define ERASE tdev->cc[_VERASE]
58 #define KILL tdev->cc[_VKILL]
59 #define INTR tdev->cc[_VINTR]
60 #define QUIT tdev->cc[_VQUIT]
61 #define SUSP tdev->cc[_VSUSP]
64 // Keep all cc's (except VMIN & VTIME) up to L2 cache.
65 for (size_t i = 0; i < _VMIN; i++) {
66 prefetch_rd(&tdev->cc[i], 2);
70 while (rbuffer_get(raw, &c) && allow_more) {
72 if (c == '\r' && ((_if & _ICRNL) || (_of & _OCRNL))) {
74 } else if (c == '\n') {
75 if ((_if & _INLCR) || (_of & (_ONLRET | _ONLCR))) {
81 if ((_if & _BRKINT)) {
82 raise_sig(tdev, lbuf, SIGINT);
86 if ((_if & _IGNBRK)) {
91 if ('a' <= c && c <= 'z') {
94 } else if ((_of & _OLCUC)) {
100 latest_eol = cooked->ptr + 1;
101 if (!out && (_lf & _ECHONL)) {
102 rbuffer_put(output, c);
111 // For input procesing
113 if (c == '\n' || c == EOL) {
114 lbuf->sflags |= LSTATE_EOL;
116 } else if (c == EOF) {
117 lbuf->sflags |= LSTATE_EOF;
120 } else if (c == INTR) {
121 raise_sig(tdev, lbuf, SIGINT);
122 } else if (c == QUIT) {
123 raise_sig(tdev, lbuf, SIGKILL);
125 } else if (c == SUSP) {
126 raise_sig(tdev, lbuf, SIGSTOP);
127 } else if (c == ERASE) {
128 rbuffer_erase(cooked);
137 rbuffer_put(output, c);
139 if ((_lf & _ECHOE) && c == ERASE) {
140 rbuffer_erase(output);
142 if ((_lf & _ECHOK) && c == KILL) {
143 rbuffer_put(output, c);
144 rbuffer_put(output, '\n');
148 allow_more = rbuffer_put(cooked, c);
151 if (out || (_lf & _IEXTEN)) {
153 lcntl_invoke_slaves(tdev, lbuf, c);
156 if (should_flush && !(_lf & _NOFLSH)) {
164 lcntl_transform_inseq(struct term* tdev)
166 return lcntl_transform_seq(tdev, &tdev->line_in, false);
170 lcntl_transform_outseq(struct term* tdev)
172 return lcntl_transform_seq(tdev, &tdev->line_in, true);