feat: a better boot command line parser
[lunaix-os.git] / lunaix-os / hal / term / lcntls / lcntl.c
index 435983040885070ed27120fa18263a17d38e0289..fdaf244275811feb83a4e5b876cefa199b72602f 100644 (file)
@@ -21,25 +21,7 @@ raise_sig(struct term* at_term, struct linebuffer* lbuf, int sig)
     lbuf->sflags |= LSTATE_SIGRAISE;
 }
 
     lbuf->sflags |= LSTATE_SIGRAISE;
 }
 
-static inline int
-lcntl_invoke_slaves(struct term* tdev, struct linebuffer* lbuf, char c)
-{
-    int allow_more = 0;
-    struct term_lcntl *lcntl, *n;
-    llist_for_each(lcntl, n, &tdev->lcntl_stack, lcntls)
-    {
-        allow_more = lcntl->process_and_put(tdev, lbuf, c);
-        if (!allow_more) {
-            break;
-        }
-
-        line_flip(lbuf);
-    }
-
-    return allow_more;
-}
-
-static inline int optimize("ipa-cp-clone")
+static inline int must_inline optimize("-fipa-cp-clone")
 lcntl_transform_seq(struct term* tdev, struct linebuffer* lbuf, bool out)
 {
     struct rbuffer* raw = lbuf->current;
 lcntl_transform_seq(struct term* tdev, struct linebuffer* lbuf, bool out)
 {
     struct rbuffer* raw = lbuf->current;
@@ -50,7 +32,9 @@ lcntl_transform_seq(struct term* tdev, struct linebuffer* lbuf, bool out)
         _lf = tdev->lflags;
     int allow_more = 1, latest_eol = cooked->ptr;
     char c;
         _lf = tdev->lflags;
     int allow_more = 1, latest_eol = cooked->ptr;
     char c;
-    bool should_flush = false;
+
+    int (*lcntl_slave_put)(struct term*, struct linebuffer*, char) =
+        tdev->lcntl->process_and_put;
 
 #define EOL tdev->cc[_VEOL]
 #define EOF tdev->cc[_VEOF]
 
 #define EOL tdev->cc[_VEOL]
 #define EOF tdev->cc[_VEOF]
@@ -72,20 +56,20 @@ lcntl_transform_seq(struct term* tdev, struct linebuffer* lbuf, bool out)
         if (c == '\r' && ((_if & _ICRNL) || (_of & _OCRNL))) {
             c = '\n';
         } else if (c == '\n') {
         if (c == '\r' && ((_if & _ICRNL) || (_of & _OCRNL))) {
             c = '\n';
         } else if (c == '\n') {
-            if ((_if & _INLCR) || (_of & (_ONLRET | _ONLCR))) {
+            if ((_if & _INLCR) || (_of & (_ONLRET))) {
                 c = '\r';
             }
         }
 
         if (c == '\0') {
                 c = '\r';
             }
         }
 
         if (c == '\0') {
+            if ((_if & _IGNBRK)) {
+                continue;
+            }
+
             if ((_if & _BRKINT)) {
                 raise_sig(tdev, lbuf, SIGINT);
                 break;
             }
             if ((_if & _BRKINT)) {
                 raise_sig(tdev, lbuf, SIGINT);
                 break;
             }
-
-            if ((_if & _IGNBRK)) {
-                continue;
-            }
         }
 
         if ('a' <= c && c <= 'z') {
         }
 
         if ('a' <= c && c <= 'z') {
@@ -101,18 +85,16 @@ lcntl_transform_seq(struct term* tdev, struct linebuffer* lbuf, bool out)
             if (!out && (_lf & _ECHONL)) {
                 rbuffer_put(output, c);
             }
             if (!out && (_lf & _ECHONL)) {
                 rbuffer_put(output, c);
             }
-            should_flush = true;
         }
 
         if (out) {
         }
 
         if (out) {
-            goto put_char;
+            goto do_out;
         }
 
         // For input procesing
 
         if (c == '\n' || c == EOL) {
             lbuf->sflags |= LSTATE_EOL;
         }
 
         // For input procesing
 
         if (c == '\n' || c == EOL) {
             lbuf->sflags |= LSTATE_EOL;
-            goto keep;
         } else if (c == EOF) {
             lbuf->sflags |= LSTATE_EOF;
             rbuffer_clear(raw);
         } else if (c == EOF) {
             lbuf->sflags |= LSTATE_EOF;
             rbuffer_clear(raw);
@@ -126,37 +108,50 @@ lcntl_transform_seq(struct term* tdev, struct linebuffer* lbuf, bool out)
             raise_sig(tdev, lbuf, SIGSTOP);
         } else if (c == ERASE) {
             rbuffer_erase(cooked);
             raise_sig(tdev, lbuf, SIGSTOP);
         } else if (c == ERASE) {
             rbuffer_erase(cooked);
+        } else if (c == KILL) {
+            // TODO shrink the rbuffer
         } else {
             goto keep;
         }
 
         } else {
             goto keep;
         }
 
+        if ((_lf & _ECHOE) && c == ERASE) {
+            rbuffer_put(output, '\x8'); 
+            rbuffer_put(output, ' '); 
+            rbuffer_put(output, '\x8'); 
+        }
+        if ((_lf & _ECHOK) && c == KILL) {
+            rbuffer_put(output, c);
+            rbuffer_put(output, '\n');
+        }
+
         continue;
 
     keep:
         if ((_lf & _ECHO)) {
             rbuffer_put(output, c);
         }
         continue;
 
     keep:
         if ((_lf & _ECHO)) {
             rbuffer_put(output, c);
         }
-        if ((_lf & _ECHOE) && c == ERASE) {
-            rbuffer_erase(output);
-        }
-        if ((_lf & _ECHOK) && c == KILL) {
-            rbuffer_put(output, c);
-            rbuffer_put(output, '\n');
+
+        goto put_char;
+
+    do_out:
+        if (c == '\n' && (_of & _ONLCR)) {
+            rbuffer_put(cooked, '\r');
         }
 
     put_char:
         }
 
     put_char:
-        allow_more = rbuffer_put(cooked, c);
-    }
-
-    if (out || (_lf & _IEXTEN)) {
-        line_flip(lbuf);
-        lcntl_invoke_slaves(tdev, lbuf, c);
+        if (!out && (_lf & _IEXTEN) && lcntl_slave_put) {
+            allow_more = lcntl_slave_put(tdev, lbuf, c);
+        } else {
+            allow_more = rbuffer_put(cooked, c);
+        }
     }
 
     }
 
-    if (should_flush && !(_lf & _NOFLSH)) {
+    if (!rbuffer_empty(output) && !(_lf & _NOFLSH)) {
         term_flush(tdev);
     }
 
         term_flush(tdev);
     }
 
+    line_flip(lbuf);
+
     return i;
 }
 
     return i;
 }
 
@@ -169,5 +164,5 @@ lcntl_transform_inseq(struct term* tdev)
 int
 lcntl_transform_outseq(struct term* tdev)
 {
 int
 lcntl_transform_outseq(struct term* tdev)
 {
-    return lcntl_transform_seq(tdev, &tdev->line_in, true);
+    return lcntl_transform_seq(tdev, &tdev->line_out, true);
 }
\ No newline at end of file
 }
\ No newline at end of file