📄 linedisc_buddy.c
字号:
uint32_t event_mask = CharSrc_ALL_Events; uint32_t numRet; uint32_t numToGet; if (SHARED.readerWants == UINT32_MAX) { /* no reader */ numToGet = DATABUFF_END - BUDDY.buffPos; DEBUG(waitevent) kprintf(KR_OSTREAM, "LineDiscBuddy: no reader -- numToGet %04x\n", numToGet); } else { uint32_t got = BUDDY.buffPos - DATABUFF; DEBUG(waitevent) kprintf(KR_OSTREAM, "LineDiscBuddy: reader -- got %04x, wants %04x\n", got, SHARED.readerWants); if (got >= SHARED.readerWants) { DEBUG(waitevent) kprintf(KR_OSTREAM, "LineDiscBuddy: reader got what he wants -- " "post FilledBufferEvent\n"); POST_EVENT(CharSrc_FilledBufferEvent); if (READER_READY()) { raw_fork_reader(SHARED.readerWants); return; } return; } else { numToGet = SHARED.readerWants - got; DEBUG(waitevent) kprintf(KR_OSTREAM, "LineDiscBuddy: Reader needs %04x\n", numToGet); } } while (RC_OK == charsrc_wait_for_event(KR_CHRSRC, numToGet, BUDDY.buffPos, &numRet, event_mask, &BUDDY.chrSrcEvents)) { DEBUG(waitevent) kprintf(KR_OSTREAM, "LineDiscBuddy: WaitForEvent returned. (numRet %03x, " "events %02x)\n", numRet, BUDDY.chrSrcEvents); BUDDY.wakeupEvents |= (BUDDY.chrSrcEvents & CharSrc_UserEventMask); if (SHARED.postedEvents) { DEBUG(postevent) kprintf(KR_OSTREAM, "LineDiscBuddy: Posting events %02x\n",SHARED.postedEvents); BUDDY.currentLDEvents |= SHARED.postedEvents; SHARED.postedEvents = 0u; } BUDDY.wakeupEvents &= ~LD_Wakeup_EventPosted; if (WBUFF_NUM_WRITTEN(&SHARED.wrt_buff) != 0u) { DEBUG(write) kprintf(KR_OSTREAM, "LineDiscBuddy: Calling tty_write\n"); try_write(); } BUDDY.wakeupEvents &= ~LD_Wakeup_WriteRequest; /* process the characters */ if (BUDDY.curInpFlags & LD_In_DoInpProc) { rawInputProcess(BUDDY.buffPos, numRet); } /* mark then as processed */ if (numRet) { BUDDY.buffPos += numRet; } /* process events -- first, post any events from above that aren't * for me. */ POST_EVENT(BUDDY.chrSrcEvents & ~(CharSrc_FilledBufferEvent | CharSrc_UserEventMask)); /* then, if we have a reader, check readerwants. */ if (SHARED.readerWants != UINT32_MAX) { uint32_t got = BUDDY.buffPos - DATABUFF; if (got >= SHARED.readerWants) { POST_EVENT(CharSrc_FilledBufferEvent); numToGet = 0u; } else { numToGet = SHARED.readerWants - got; } } if (WBUFF_NUM_WRITTEN(&SHARED.wrt_buff) != 0u) try_write(); if (READER_READY()) raw_fork_reader(SHARED.readerWants); if (SHARED.readerWants == UINT32_MAX) { /* no reader */ numToGet = DATABUFF_END - BUDDY.buffPos; } if (BUDDY.wakeupEvents) break; /* FIXME: flush buffer? */ } kprintf(KR_OSTREAM, "Linedisc_buddy -- end of loop!\n"); return;}uint8_t *linemode_find_first_special_char(void){ /* find the first non-escaped control character */ register uint8_t *pos; register uint8_t *end = BUDDY.buffPos; cc_type quote_char = BUDDY.current_CC[LD_CC_Quote]; if (quote_char) { /* we have to check for quoted chars */ int quoted = 0; for (pos = DATABUFF; pos < end; pos++) { if (quoted) continue; if (CCLASS(*pos) == CC_NEWLINE) break; else if (*pos == (uint8_t)quote_char) quoted = 1; else if (CHECK_CHAR(SHARED.char_mask,*pos)) break; /* this is a special character */ } } else { for (pos = DATABUFF; pos < end; pos++) { if (CCLASS(*pos) == CC_NEWLINE || CHECK_CHAR(SHARED.char_mask,*pos)) break; } } if (pos == end) { return NULL; /* no special characters */ } return pos;}voidlinemode_fork_reader(void){ uint32_t numBytes; /* SEND to the reader. */ if (BUDDY.currentLDEvents & CharSrc_SpecialCharEvent) { if (!BUDDY.first_special) { kdprintf(KR_OSTREAM, "LineDisc_Buddy: HEY! I can't find the " "special character to end the line!\n"); /* for now, send the whole thing, I guess */ numBytes = BUDDY.buffPos - DATABUFF; } else { numBytes = BUDDY.first_special - DATABUFF + 1; /* include first special */ } } else { numBytes = 0; /* Don't have a full line yet. */ } DEBUG(waitevent) kprintf(KR_OSTREAM, " actualBytes: %d\n",numBytes); fork_reader(numBytes); /* do the fork and update the buffer */ /* update the first_special pointer */ BUDDY.first_special = linemode_find_first_special_char(); if (BUDDY.first_special) POST_EVENT(CharSrc_SpecialCharEvent);}voidlinemode_echo(uint8_t theChar) { uint8_t theOut[3] = {theChar,0,0}; if ( !ISSET(BUDDY.curInpFlags, LD_In_Echo) ) return; if (CCLASS(theChar) != 0 && ISSET(BUDDY.curInpFlags, LD_In_EchoCtrl) && CCLASS(theChar) != CC_NEWLINE && CCLASS(theChar) != CC_TAB) { theOut[0] = '^'; theOut[1] = (theChar == 0x7F)? '?':theChar + 'A' - 1; } write_string(theOut);}voidlineModeProcess(uint32_t numRet) /* process chars in linemode */{ register uint8_t *curChar = BUDDY.buffPos; for (; numRet > 0; numRet--,curChar++) { /* basically a large case statement. Continue when done with character (make sure to increment buffPos if necessary */ uint32_t pos = BUDDY.buffPos - DATABUFF; assert(pos < EROS_PAGE_SIZE); if (pos == EROS_PAGE_SIZE - 1) { write_beep(); continue; } if (ISSET(BUDDY.curInpFlags,LD_In_SwapCRNL)) { switch (*curChar) { case '\n': *curChar = '\r'; break; case '\r': *curChar = '\n'; break; } } if (pos == EROS_PAGE_SIZE - 2) { /* we are running out of space -- Accept a special character for the 2nd to last character, and nothing for the last (we must wait until the data is returned */ if (BUDDY.quoteNext == 1 || (CCLASS(*curChar) != CC_NEWLINE && CHECK_CHAR(BUDDY.cur_char_mask,*curChar))) { write_beep(); BUDDY.quoteNext = 0; continue; } } if (BUDDY.quoteNext) { BUDDY.quoteNext = 0; linemode_echo(*curChar); *BUDDY.buffPos++ = *curChar; continue; } else { /* not quoted */ if (CCLASS(*curChar) == CC_NEWLINE) goto is_special_character; /* goto the real routine */ if (*curChar != 0) { /* possibly a controlling character -- this way, we don't have to check if the control character is set. */ if (*curChar == BUDDY.current_CC[LD_CC_Erase] || *curChar == BUDDY.current_CC[LD_CC_AltErase]) { if (pos == 0) continue; BUDDY.buffPos--; /* remove the previous character */ if (ISSET(BUDDY.curInpFlags,LD_In_VisErase)) {#if 0 linemode_rubout(*BUDDY.buffPos);#else char str[2] = {BUDDY.current_CC[LD_CC_Erase],0}; write_string(str);#endif } else { linemode_echo(BUDDY.current_CC[LD_CC_Erase]); } if (BUDDY.buffPos > DATABUFF && BUDDY.current_CC[LD_CC_Quote] && *(BUDDY.buffPos - 1) == BUDDY.current_CC[LD_CC_Quote]) {#if 0 /* we need to check if this is quoted. What we do is count the number of consecutive quote chars before this character, and if it is odd, eat the first one. */#else BUDDY.buffPos--; /* for now, just assume no-one quotes the Quote character */#endif } continue; } if (*curChar == BUDDY.current_CC[LD_CC_EraseWord]) { continue; /* FIXME: implement */ } if (*curChar == BUDDY.current_CC[LD_CC_KillLine]) { continue; /* FIXME: implement */ } if (*curChar == BUDDY.current_CC[LD_CC_Reprint]) { continue; /* FIXME: implement */ } if (*curChar == BUDDY.current_CC[LD_CC_Quote]) { if (ISSET(BUDDY.curInpFlags,LD_In_Echo)) { if (ISSET(BUDDY.curInpFlags,LD_In_EchoCtrl) && ISSET(BUDDY.curInpFlags,LD_In_VisErase)) { uint8_t toSend[] = {'^', BUDDY.current_CC[LD_CC_Erase], 0}; write_string(toSend); } else { linemode_echo(*curChar); } } *BUDDY.buffPos++ = *curChar; BUDDY.quoteNext = 1; continue; } } /* if (*curChar != 0) */ if (CHECK_CHAR(BUDDY.cur_char_mask,*curChar)) { /* this is a special character */ linemode_echo(*curChar); /* echo it */ is_special_character: /* from '\n' check */ *BUDDY.buffPos = *curChar; POST_EVENT(CharSrc_SpecialCharEvent); if (!BUDDY.first_special) { BUDDY.first_special = BUDDY.buffPos; } BUDDY.buffPos++; /* no matter what character it was, afterwards we echo carriage return */ if (ISSET(BUDDY.curInpFlags,LD_In_AlwEchoNL) || ISSET(BUDDY.curInpFlags,LD_In_Echo)) write_string("\n"); } else { /* this is a normal character */ linemode_echo(*curChar); BUDDY.buffPos++; } } }}/* FIXME: Currently, linemode makes assumptions that come down to the calling person is expected to be able to handle the full buffer size -- EROS_PAGE_SIZE. */voidlineModeLoop(void){ uint32_t event_mask = CharSrc_ALL_Events; uint32_t numRet; uint32_t numToGet; if (SHARED.readerWants != UINT32_MAX) { /* there is a reader -- check if he we're ready */ if (READER_READY()) { linemode_fork_reader(); return; } } /* no timeouts for now -- read input a character at a time. */ /* NOTE: we must never let BUDDY.buffPos get out of the page */ numToGet = 1; while (RC_OK == charsrc_wait_for_event(KR_CHRSRC, numToGet, BUDDY.buffPos, &numRet, event_mask, &BUDDY.chrSrcEvents)) { DEBUG(waitevent) kprintf(KR_OSTREAM, "LineDiscBuddy: WaitForEvent returned. (numRet %03x, " "events %08x, %sreader)\n", numRet, BUDDY.chrSrcEvents, (SHARED.readerWants == UINT32_MAX)?"no ":""); BUDDY.wakeupEvents |= (BUDDY.chrSrcEvents & CharSrc_UserEventMask); if (SHARED.postedEvents) { DEBUG(postevent) kprintf(KR_OSTREAM, "LineDiscBuddy: Posting events %02x\n",SHARED.postedEvents); BUDDY.currentLDEvents |= SHARED.postedEvents; SHARED.postedEvents = 0u; } BUDDY.wakeupEvents &= ~LD_Wakeup_EventPosted; if (WBUFF_NUM_WRITTEN(&SHARED.wrt_buff) != 0u) { DEBUG(write) kprintf(KR_OSTREAM, "LineDiscBuddy: Calling tty_write\n"); try_write(); } else if (BUDDY.chrSrcEvents & CharSrc_WriteSpaceAvailEvent) { POST_EVENT(CharSrc_WriteSpaceAvailEvent); } BUDDY.wakeupEvents &= ~LD_Wakeup_WriteRequest; lineModeProcess(numRet); /* process the characters */ /* BUDDY.buffPos now points to the end of the characters. */ /* any applicable events have been posted. */ /* POST_EVENT(BUDDY.chrSrcEvents & ~(CharSrc_FilledBufferEvent | CharSrc_UserEventMask)); */ if (WBUFF_NUM_WRITTEN(&SHARED.wrt_buff) != 0u) try_write(); if (READER_READY()) linemode_fork_reader(); if (BUDDY.wakeupEvents) break; /* FIXME: flush buffer? */ } kprintf(KR_OSTREAM, "Linedisc_buddy -- end of loop!\n"); return;}voidraw_update_specialChars(void){ uint16_t buff[256]; uint16_t *buffp = buff; uint32_t idx; for (idx = 0; idx < 256; idx++) { if (CHECK_CHAR(BUDDY.cur_char_mask,idx)) *buffp++ = idx; } charsrc_set_special_chars(KR_CHRSRC, buff, buffp - buff);}voidline_update_specialChars(void){ uint16_t buff[256 + LD_Num_CC + 1]; /* overkill, but guarenteed to work */ uint16_t *buffp = buff; uint32_t idx; DEBUG(control) kprintf(KR_OSTREAM,"LineDisc_buddy: Updating line-mode special chars:"); for (idx = 0; idx < 256; idx++) { if (CHECK_CHAR(BUDDY.cur_char_mask,idx)) { DEBUG(control) kprintf(KR_OSTREAM," 0x%02x",idx); *buffp++ = idx; } } for (idx = 0; idx < LD_Num_CC; idx++) { uint16_t curChar = BUDDY.current_CC[idx]; if (curChar) { /* the control character is active */ if (((curChar & 0xFF) == curChar) && CHECK_CHAR(BUDDY.cur_char_mask,(uint8_t)curChar)) { DEBUG(control) kprintf(KR_OSTREAM," *0x%02x*",curChar); } else { DEBUG(control) kprintf(KR_OSTREAM," 0x%02x",curChar); *buffp++ = curChar; } } } if (!CHECK_CHAR(BUDDY.cur_char_mask,'\r')) { DEBUG(control) kprintf(KR_OSTREAM," \\r"); *buffp++ = '\r'; } DEBUG(control) kdprintf(KR_OSTREAM," total %d\n",buffp-buff); charsrc_set_special_chars(KR_CHRSRC, buff, buffp - buff);}int main(void){ initialize_linedisc_buddy(); /* either successful or destroys me. */ DEBUG(init) kprintf(KR_OSTREAM, "LineDiscBuddy: Initialization successful\n"); while (1) { uint32_t update_special_chars = 0; uint32_t new_flags = SHARED.inpProcFlags; if (ISSET(BUDDY.wakeupEvents,LD_Wakeup_Chars)) { DEBUG(control) kdprintf(KR_OSTREAM, "Linedisc_buddy: Copying control_chars and char_mask\n"); memcpy(BUDDY.current_CC, (const char *)SHARED.control_chars, /* cast away volatile */ sizeof(SHARED.control_chars)); memcpy(BUDDY.cur_char_mask, (const char *)SHARED.char_mask, /* cast away volatile */ sizeof(SHARED.control_chars)); update_special_chars = 1; BUDDY.wakeupEvents &= ~LD_Wakeup_Chars; } if (BUDDY.curInpFlags != new_flags) { uint32_t inpProc = (BUDDY.curInpFlags & LD_In_DoInpProc); uint32_t nowInpProc = (new_flags & LD_In_DoInpProc); uint32_t lineMode = (BUDDY.curInpFlags & LD_In_LineMode); uint32_t nowLineMode = (new_flags & LD_In_LineMode); if ((inpProc && lineMode) && (!nowInpProc || !nowLineMode)) { /* line-mode to raw-mode */ update_special_chars = 1; /* for now, flush all of the data */ BUDDY.buffPos = DATABUFF; write_string("\r\nNow in raw mode\r\n"); } if ((!inpProc || !lineMode) && (nowInpProc && nowLineMode)) { /* raw -> line mode */ update_special_chars = 1; BUDDY.buffPos = DATABUFF; BUDDY.quoteNext = 0; BUDDY.topWrote = 0; BUDDY.first_special = NULL; write_string("\r\nNow in line mode\r\n"); } /* assume for now that any other changes are safe */ BUDDY.curInpFlags = new_flags; BUDDY.wakeupEvents &= ~LD_Wakeup_ProcFlags; } BUDDY.curInpFlags = new_flags; DEBUG(control) kprintf(KR_OSTREAM, "Linedisc_buddy: entering main loop. %s spc_chars_upd\n", update_special_chars?"YES":"no"); if (!(BUDDY.curInpFlags & LD_In_DoInpProc) || !(BUDDY.curInpFlags & LD_In_LineMode)) { DEBUG(inpproc) kdprintf(KR_OSTREAM,"Hey! We're in raw mode!\n"); if (update_special_chars) raw_update_specialChars(); rawLoop(); } else { if (update_special_chars) line_update_specialChars(); lineModeLoop(); } /* we've checked it */ BUDDY.wakeupEvents &= ~LD_Wakeup_TearDown; if (SHARED.linedisc_status == LD_Stat_TearDown) { SHARED.linedisc_status = LD_Stat_Gone; destroy_self(RC_OK); /* NOTREACHED */ break; } } kdprintf(KR_OSTREAM, "Linedisc_buddy -- broke out of main!\n"); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -