Xv6 with picoc & Linkage editor  v1.0
The project delineate mutual cohesion between c library, linkage editor ( linker), interpreter and operating system by porting the same on xv6 kernel
console.c
00001 // Console input and output.
00002 // Input is from the keyboard or serial port.
00003 // Output is written to the screen and serial port.
00004 
00005 #include "types.h"
00006 #include "defs.h"
00007 #include "param.h"
00008 #include "traps.h"
00009 #include "spinlock.h"
00010 #include "fs.h"
00011 #include "file.h"
00012 #include "memlayout.h"
00013 #include "mmu.h"
00014 #include "proc.h"
00015 #include "x86.h"
00016 
00017 static void consputc(int);
00018 
00019 static int panicked = 0;
00020 
00021 static struct {
00022   struct spinlock lock;
00023   int locking;
00024 } cons;
00025 
00026 static void
00027 printint(int xx, int base, int sign)
00028 {
00029   static char digits[] = "0123456789abcdef";
00030   char buf[16];
00031   int i;
00032   uint x;
00033 
00034   if(sign && (sign = xx < 0))
00035     x = -xx;
00036   else
00037     x = xx;
00038 
00039   i = 0;
00040   do{
00041     buf[i++] = digits[x % base];
00042   }while((x /= base) != 0);
00043 
00044   if(sign)
00045     buf[i++] = '-';
00046 
00047   while(--i >= 0)
00048     consputc(buf[i]);
00049 }
00050 //PAGEBREAK: 50
00051 
00052 // Print to the console. only understands %d, %x, %p, %s.
00053 void
00054 cprintf(char *fmt, ...)
00055 {
00056   int i, c, locking;
00057   uint *argp;
00058   char *s;
00059 
00060   locking = cons.locking;
00061   if(locking)
00062     acquire(&cons.lock);
00063 
00064   if (fmt == 0)
00065     panic("null fmt");
00066 
00067   argp = (uint*)(void*)(&fmt + 1);
00068   for(i = 0; (c = fmt[i] & 0xff) != 0; i++){
00069     if(c != '%'){
00070       consputc(c);
00071       continue;
00072     }
00073     c = fmt[++i] & 0xff;
00074     if(c == 0)
00075       break;
00076     switch(c){
00077     case 'd':
00078       printint(*argp++, 10, 1);
00079       break;
00080     case 'x':
00081     case 'p':
00082       printint(*argp++, 16, 0);
00083       break;
00084     case 's':
00085       if((s = (char*)*argp++) == 0)
00086         s = "(null)";
00087       for(; *s; s++)
00088         consputc(*s);
00089       break;
00090     case '%':
00091       consputc('%');
00092       break;
00093     default:
00094       // Print unknown % sequence to draw attention.
00095       consputc('%');
00096       consputc(c);
00097       break;
00098     }
00099   }
00100 
00101   if(locking)
00102     release(&cons.lock);
00103 }
00104 
00105 void
00106 panic(char *s)
00107 {
00108   int i;
00109   uint pcs[10];
00110   
00111   cli();
00112   cons.locking = 0;
00113   cprintf("cpu%d: panic: ", cpu->id);
00114   cprintf(s);
00115   cprintf("\n");
00116   getcallerpcs(&s, pcs);
00117   for(i=0; i<10; i++)
00118     cprintf(" %p", pcs[i]);
00119   panicked = 1; // freeze other CPU
00120   for(;;)
00121     ;
00122 }
00123 
00124 //PAGEBREAK: 50
00125 #define BACKSPACE 0x100
00126 #define CRTPORT 0x3d4
00127 static ushort *crt = (ushort*)P2V(0xb8000);  // CGA memory
00128 
00129 static void
00130 cgaputc(int c)
00131 {
00132   int pos;
00133   
00134   // Cursor position: col + 80*row.
00135   outb(CRTPORT, 14);
00136   pos = inb(CRTPORT+1) << 8;
00137   outb(CRTPORT, 15);
00138   pos |= inb(CRTPORT+1);
00139 
00140   if(c == '\n')
00141     pos += 80 - pos%80;
00142   else if(c == BACKSPACE){
00143     if(pos > 0) --pos;
00144   } else
00145     crt[pos++] = (c&0xff) | 0x0700;  // black on white
00146   
00147   if((pos/80) >= 24){  // Scroll up.
00148     memmove(crt, crt+80, sizeof(crt[0])*23*80);
00149     pos -= 80;
00150     memset(crt+pos, 0, sizeof(crt[0])*(24*80 - pos));
00151   }
00152   
00153   outb(CRTPORT, 14);
00154   outb(CRTPORT+1, pos>>8);
00155   outb(CRTPORT, 15);
00156   outb(CRTPORT+1, pos);
00157   crt[pos] = ' ' | 0x0700;
00158 }
00159 
00160 void
00161 consputc(int c)
00162 {
00163   if(panicked){
00164     cli();
00165     for(;;)
00166       ;
00167   }
00168 
00169   if(c == BACKSPACE){
00170     uartputc('\b'); uartputc(' '); uartputc('\b');
00171   } else
00172     uartputc(c);
00173   cgaputc(c);
00174 }
00175 
00176 #define INPUT_BUF 128
00177 struct {
00178   struct spinlock lock;
00179   char buf[INPUT_BUF];
00180   uint r;  // Read index
00181   uint w;  // Write index
00182   uint e;  // Edit index
00183 } input;
00184 
00185 #define C(x)  ((x)-'@')  // Control-x
00186 
00187 void
00188 consoleintr(int (*getc)(void))
00189 {
00190   int c;
00191 
00192   acquire(&input.lock);
00193   while((c = getc()) >= 0){
00194     switch(c){
00195     case C('P'):  // Process listing.
00196       procdump();
00197       break;
00198     case C('U'):  // Kill line.
00199       while(input.e != input.w &&
00200             input.buf[(input.e-1) % INPUT_BUF] != '\n'){
00201         input.e--;
00202         consputc(BACKSPACE);
00203       }
00204       break;
00205     case C('H'): case '\x7f':  // Backspace
00206       if(input.e != input.w){
00207         input.e--;
00208         consputc(BACKSPACE);
00209       }
00210       break;
00211     default:
00212       if(c != 0 && input.e-input.r < INPUT_BUF){
00213         c = (c == '\r') ? '\n' : c;
00214         input.buf[input.e++ % INPUT_BUF] = c;
00215         consputc(c);
00216         if(c == '\n' || c == C('D') || input.e == input.r+INPUT_BUF){
00217           input.w = input.e;
00218           wakeup(&input.r);
00219         }
00220       }
00221       break;
00222     }
00223   }
00224   release(&input.lock);
00225 }
00226 
00227 int
00228 consoleread(struct inode *ip, char *dst, int n)
00229 {
00230   uint target;
00231   int c;
00232 
00233   iunlock(ip);
00234   target = n;
00235   acquire(&input.lock);
00236   while(n > 0){
00237     while(input.r == input.w){
00238       if(proc->killed){
00239         release(&input.lock);
00240         ilock(ip);
00241         return -1;
00242       }
00243       sleep(&input.r, &input.lock);
00244     }
00245     c = input.buf[input.r++ % INPUT_BUF];
00246     if(c == C('D')){  // EOF
00247       if(n < target){
00248         // Save ^D for next time, to make sure
00249         // caller gets a 0-byte result.
00250         input.r--;
00251       }
00252       break;
00253     }
00254     *dst++ = c;
00255     --n;
00256     if(c == '\n')
00257       break;
00258   }
00259   release(&input.lock);
00260   ilock(ip);
00261 
00262   return target - n;
00263 }
00264 
00265 int
00266 consolewrite(struct inode *ip, char *buf, int n)
00267 {
00268   int i;
00269 
00270   iunlock(ip);
00271   acquire(&cons.lock);
00272   for(i = 0; i < n; i++)
00273     consputc(buf[i] & 0xff);
00274   release(&cons.lock);
00275   ilock(ip);
00276 
00277   return n;
00278 }
00279 
00280 void
00281 consoleinit(void)
00282 {
00283   initlock(&cons.lock, "console");
00284   initlock(&input.lock, "input");
00285 
00286   devsw[CONSOLE].write = consolewrite;
00287   devsw[CONSOLE].read = consoleread;
00288   cons.locking = 1;
00289 
00290   picenable(IRQ_KBD);
00291   ioapicenable(IRQ_KBD, 0);
00292 }
00293 
 All Data Structures