| // Console input and output. | |
| // Input is from the keyboard or serial port. | |
| // Output is written to the screen and serial port. | |
| static void consputc(int); | |
| static int panicked = 0; | |
| static struct | |
| { | |
| struct spinlock lock; | |
| int locking; | |
| } cons; | |
| int back_count = 0; | |
| static void | |
| printint(int xx, int base, int sign) | |
| { | |
| static char digits[] = "0123456789abcdef"; | |
| char buf[16]; | |
| int i; | |
| uint x; | |
| if (sign && (sign = xx < 0)) | |
| x = -xx; | |
| else | |
| x = xx; | |
| i = 0; | |
| do | |
| { | |
| buf[i++] = digits[x % base]; | |
| } while ((x /= base) != 0); | |
| if (sign) | |
| buf[i++] = '-'; | |
| while (--i >= 0) | |
| consputc(buf[i]); | |
| } | |
| // PAGEBREAK: 50 | |
| // Print to the console. only understands %d, %x, %p, %s. | |
| void cprintf(char *fmt, ...) | |
| { | |
| int i, c, locking; | |
| uint *argp; | |
| char *s; | |
| locking = cons.locking; | |
| if (locking) | |
| acquire(&cons.lock); | |
| if (fmt == 0) | |
| panic("null fmt"); | |
| argp = (uint *)(void *)(&fmt + 1); | |
| for (i = 0; (c = fmt[i] & 0xff) != 0; i++) | |
| { | |
| if (c != '%') | |
| { | |
| consputc(c); | |
| continue; | |
| } | |
| c = fmt[++i] & 0xff; | |
| if (c == 0) | |
| break; | |
| switch (c) | |
| { | |
| case 'd': | |
| printint(*argp++, 10, 1); | |
| break; | |
| case 'x': | |
| case 'p': | |
| printint(*argp++, 16, 0); | |
| break; | |
| case 's': | |
| if ((s = (char *)*argp++) == 0) | |
| s = "(null)"; | |
| for (; *s; s++) | |
| consputc(*s); | |
| break; | |
| case '%': | |
| consputc('%'); | |
| break; | |
| default: | |
| // Print unknown % sequence to draw attention. | |
| consputc('%'); | |
| consputc(c); | |
| break; | |
| } | |
| } | |
| if (locking) | |
| release(&cons.lock); | |
| } | |
| void panic(char *s) | |
| { | |
| int i; | |
| uint pcs[10]; | |
| cli(); | |
| cons.locking = 0; | |
| // use lapiccpunum so that we can call panic from mycpu() | |
| cprintf("lapicid %d: panic: ", lapicid()); | |
| cprintf(s); | |
| cprintf("\n"); | |
| getcallerpcs(&s, pcs); | |
| for (i = 0; i < 10; i++) | |
| cprintf(" %p", pcs[i]); | |
| panicked = 1; // freeze other CPU | |
| for (;;) | |
| ; | |
| } | |
| // PAGEBREAK: 50 | |
| static ushort *crt = (ushort *)P2V(0xb8000); // CGA memory | |
| static void | |
| cgaputc(int c) | |
| { | |
| int pos; | |
| // Cursor position: col + 80*row. | |
| outb(CRTPORT, 14); | |
| pos = inb(CRTPORT + 1) << 8; | |
| outb(CRTPORT, 15); | |
| pos |= inb(CRTPORT + 1); | |
| if (c == '\n') | |
| pos += 80 - pos % 80; | |
| else if (c == BACKSPACE) | |
| { | |
| for (int i = pos - 1; i < pos + back_count; i++) | |
| crt[i] = crt[i + 1]; | |
| if (pos > 0) | |
| --pos; | |
| } | |
| else | |
| { | |
| for (int i = pos + back_count; i > pos; i--) | |
| crt[i] = crt[i - 1]; | |
| crt[pos] = (c & 0xff) | 0x0700; // black on white | |
| pos++; | |
| } | |
| if (pos < 0 || pos > 25 * 80) | |
| panic("pos under/overflow"); | |
| if ((pos / 80) >= 24) | |
| { // Scroll up. | |
| memmove(crt, crt + 80, sizeof(crt[0]) * 23 * 80); | |
| pos -= 80; | |
| memset(crt + pos, 0, sizeof(crt[0]) * (24 * 80 - pos)); | |
| } | |
| outb(CRTPORT, 14); | |
| outb(CRTPORT + 1, pos >> 8); | |
| outb(CRTPORT, 15); | |
| outb(CRTPORT + 1, pos); | |
| crt[pos + back_count] = ' ' | 0x0700; | |
| } | |
| void consputc(int c) | |
| { | |
| if (panicked) | |
| { | |
| cli(); | |
| for (;;) | |
| ; | |
| } | |
| if (c == BACKSPACE) | |
| { | |
| uartputc('\b'); | |
| uartputc(' '); | |
| uartputc('\b'); | |
| } | |
| else | |
| uartputc(c); | |
| cgaputc(c); | |
| } | |
| struct Input | |
| { | |
| char buf[INPUT_BUF]; | |
| uint r; // Read index | |
| uint w; // Write index | |
| uint e; // End index | |
| } input; | |
| struct | |
| { | |
| /* data */ | |
| struct Input history[INPUT_HISTORY]; | |
| int cur; | |
| int end; | |
| int size; | |
| } inputs; | |
| static void backwardCursor() | |
| { | |
| int pos; | |
| // get cursor position | |
| outb(CRTPORT, 14); | |
| pos = inb(CRTPORT + 1) << 8; | |
| outb(CRTPORT, 15); | |
| pos |= inb(CRTPORT + 1); | |
| // move back | |
| if (crt[pos - 2] != (('$' & 0xff) | 0x0700)) | |
| pos--; | |
| // reset cursor | |
| outb(CRTPORT, 14); | |
| outb(CRTPORT + 1, pos >> 8); | |
| outb(CRTPORT, 15); | |
| outb(CRTPORT + 1, pos); | |
| back_count++; | |
| } | |
| static void forwardCursor() | |
| { | |
| int pos; | |
| // get cursor position | |
| outb(CRTPORT, 14); | |
| pos = inb(CRTPORT + 1) << 8; | |
| outb(CRTPORT, 15); | |
| pos |= inb(CRTPORT + 1); | |
| // move forward | |
| pos++; | |
| // reset cursor | |
| outb(CRTPORT, 14); | |
| outb(CRTPORT + 1, pos >> 8); | |
| outb(CRTPORT, 15); | |
| outb(CRTPORT + 1, pos); | |
| back_count--; | |
| } | |
| void displaylastcommand() | |
| { | |
| for (int i = (input.w); i < input.e; i++) | |
| { | |
| consputc(input.buf[i]); | |
| } | |
| } | |
| void displayclear() | |
| { | |
| for (int i = 0; i < back_count; i++) | |
| forwardCursor(); | |
| back_count = 0; | |
| int end = input.e; | |
| while (end != input.w && | |
| input.buf[(end - 1) % INPUT_BUF] != '\n') | |
| { | |
| end--; | |
| consputc(BACKSPACE); | |
| } | |
| } | |
| static void shiftright(char *buf) | |
| { | |
| for (int i = input.e; i > input.e - back_count; i--) | |
| { | |
| buf[(i) % INPUT_BUF] = buf[(i - 1) % INPUT_BUF]; // Shift elements to the right | |
| } | |
| } | |
| static void shiftleft(char *buf) | |
| { | |
| for (int i = input.e - back_count - 1; i < input.e; i++) | |
| { | |
| buf[(i) % INPUT_BUF] = buf[(i + 1) % INPUT_BUF]; // Shift elements to the right | |
| } | |
| input.buf[input.e] = ' '; | |
| } | |
| static void arrowup() | |
| { | |
| if (inputs.cur == inputs.end) | |
| { | |
| inputs.history[inputs.end % INPUT_HISTORY] = input; | |
| } | |
| displayclear(); | |
| input = inputs.history[--inputs.cur % INPUT_HISTORY]; | |
| input.buf[--input.e] = '\0'; | |
| displaylastcommand(); | |
| } | |
| static void arrowdown() | |
| { | |
| if (inputs.cur < inputs.end) | |
| { | |
| displayclear(); | |
| input = inputs.history[++inputs.cur % INPUT_HISTORY]; | |
| if (input.e != input.w && inputs.cur != inputs.end) | |
| input.buf[--input.e] = '\0'; | |
| displaylastcommand(); | |
| } | |
| } | |
| static void clearscreen() | |
| { | |
| for (int i = 0; i < back_count; i++) | |
| forwardCursor(); | |
| back_count = 0; | |
| int pos; | |
| // get cursor position | |
| outb(CRTPORT, 14); | |
| pos = inb(CRTPORT + 1) << 8; | |
| outb(CRTPORT, 15); | |
| pos |= inb(CRTPORT + 1); | |
| while (pos) | |
| { | |
| consputc(BACKSPACE); | |
| pos--; | |
| } | |
| input.e = input.w = input.r = 0; | |
| consputc('$'); | |
| consputc(' '); | |
| pos += 2; | |
| // reset cursor | |
| outb(CRTPORT, 14); | |
| outb(CRTPORT + 1, pos >> 8); | |
| outb(CRTPORT, 15); | |
| outb(CRTPORT + 1, pos); | |
| } | |
| void consoleintr(int (*getc)(void)) | |
| { | |
| int c, doprocdump = 0; | |
| acquire(&cons.lock); | |
| while ((c = getc()) >= 0) | |
| { | |
| switch (c) | |
| { | |
| case C('P'): // Process listing. | |
| // procdump() locks cons.lock indirectly; invoke later | |
| doprocdump = 1; | |
| back_count = 0; | |
| break; | |
| case C('U'): // Kill line. | |
| displayclear(); | |
| while (input.e != input.w && | |
| input.buf[(input.e - 1) % INPUT_BUF] != '\n') | |
| input.e--; | |
| break; | |
| case C('H'): | |
| case '\x7f': // Backspace | |
| if (input.e != input.w && input.e - input.w > back_count) | |
| { | |
| if (back_count > 0) | |
| shiftleft(input.buf); | |
| input.e--; | |
| consputc(BACKSPACE); | |
| } | |
| break; | |
| case C('B'): | |
| if ((input.e - back_count) > input.w) | |
| backwardCursor(); | |
| break; | |
| case C('F'): | |
| if (back_count > 0) | |
| forwardCursor(); | |
| break; | |
| case C('L'): | |
| clearscreen(); | |
| inputs.cur = inputs.end; | |
| break; | |
| case 226: | |
| if (inputs.size && inputs.end - inputs.cur < inputs.size) | |
| arrowup(); | |
| break; | |
| case 227: | |
| if (inputs.size && inputs.end - inputs.cur > 0) | |
| arrowdown(); | |
| break; | |
| default: | |
| if (c != 0 && input.e - input.r < INPUT_BUF) | |
| { | |
| c = (c == '\r') ? '\n' : c; | |
| if (c == '\n') | |
| back_count = 0; | |
| shiftright(input.buf); | |
| input.buf[(input.e++ - back_count) % INPUT_BUF] = c; | |
| consputc(c); | |
| if (c == '\n' || c == C('D') || input.e == input.r + INPUT_BUF) | |
| { | |
| inputs.history[inputs.end++ % INPUT_HISTORY] = input; | |
| inputs.cur = inputs.end; | |
| if (inputs.size < 10) | |
| inputs.size++; | |
| input.w = input.e; | |
| wakeup(&input.r); | |
| } | |
| } | |
| break; | |
| } | |
| } | |
| release(&cons.lock); | |
| if (doprocdump) | |
| { | |
| procdump(); // now call procdump() wo. cons.lock held | |
| } | |
| } | |
| int consoleread(struct inode *ip, char *dst, int n) | |
| { | |
| uint target; | |
| int c; | |
| iunlock(ip); | |
| target = n; | |
| acquire(&cons.lock); | |
| while (n > 0) | |
| { | |
| while (input.r == input.w) | |
| { | |
| if (myproc()->killed) | |
| { | |
| release(&cons.lock); | |
| ilock(ip); | |
| return -1; | |
| } | |
| sleep(&input.r, &cons.lock); | |
| } | |
| c = input.buf[input.r++ % INPUT_BUF]; | |
| if (c == C('D')) | |
| { // EOF | |
| if (n < target) | |
| { | |
| // Save ^D for next time, to make sure | |
| // caller gets a 0-byte result. | |
| input.r--; | |
| } | |
| break; | |
| } | |
| *dst++ = c; | |
| --n; | |
| if (c == '\n') | |
| break; | |
| } | |
| release(&cons.lock); | |
| ilock(ip); | |
| return target - n; | |
| } | |
| int consolewrite(struct inode *ip, char *buf, int n) | |
| { | |
| int i; | |
| iunlock(ip); | |
| acquire(&cons.lock); | |
| for (i = 0; i < n; i++) | |
| consputc(buf[i] & 0xff); | |
| release(&cons.lock); | |
| ilock(ip); | |
| return n; | |
| } | |
| void consoleinit(void) | |
| { | |
| initlock(&cons.lock, "console"); | |
| devsw[CONSOLE].write = consolewrite; | |
| devsw[CONSOLE].read = consoleread; | |
| cons.locking = 1; | |
| ioapicenable(IRQ_KBD, 0); | |
| } | |
| void | |
| printspaces(int count) | |
| { | |
| for(int i = 0; i < count; ++i) | |
| cprintf(" "); | |
| } | |
| int count_digits(int n) { | |
| int count = 0; | |
| while(n!= 0) { | |
| n/=10; | |
| ++count; | |
| } | |
| return count; | |
| } |
Xet Storage Details
- Size:
- 9.42 kB
- Xet hash:
- 45c38cab0d0476c2209d957417b335c3be70151e494042ff34c50596e3abe111
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.