1    package org.xwt.mips;
2    import java.io.*;
3    
4    public abstract class VM implements Syscalls, Errno {
5        // Register Names
6        protected final static int ZERO = 0; // Immutable, hardwired to 0
7        protected final static int AT = 1;  // Reserved for assembler
8        protected final static int K0 = 26; // Reserved for kernel 
9        protected final static int K1 = 27; // Reserved for kernel 
10       protected final static int GP = 28; // Global pointer (the middle of .sdata/.sbss)
11       protected final static int SP = 29; // Stack pointer
12       protected final static int FP = 30; // Frame Pointer
13       protected final static int RA = 31; // Return Address
14       
15       // Return values (caller saved)
16       protected final static int V0 = 2;
17       protected final static int V1 = 3;
18       // Argument Registers (caller saved)
19       protected final static int A0 = 4; 
20       protected final static int A1 = 5;
21       protected final static int A2 = 6;
22       protected final static int A3 = 7;
23       // Temporaries (caller saved)
24       protected final static int T0 = 8;
25       protected final static int T1 = 9;
26       protected final static int T2 = 10;
27       protected final static int T3 = 11;
28       protected final static int T4 = 12;
29       protected final static int T5 = 13;
30       protected final static int T6 = 14;
31       protected final static int T7 = 15;
32       protected final static int T8 = 24;
33       protected final static int T9 = 25;
34       // Saved (callee saved)
35       protected final static int S0 = 16;
36       protected final static int S1 = 17;
37       protected final static int S2 = 18;
38       protected final static int S3 = 19;
39       protected final static int S4 = 20;
40       protected final static int S5 = 21;
41       protected final static int S6 = 22;
42       protected final static int S7 = 23;
43   
44       // Page Constants
45       // Page Size: 4k
46       // Total Pages: 64k
47       // Maxiumum Addressable memory 256mb
48       // 1mb of stack space
49       protected final static int PAGE_SIZE = 4096;
50       protected final static int PAGE_WORDS = (int)(PAGE_SIZE >>> 2);
51       protected final static int PAGE_SHIFT = 12;
52       protected final static int STACK_PAGES = 256;
53       // NOTE: If you change TOTAL_PAGES crt0.c needs to be updated to reflect the
54       // new location of INITIAL_SP
55       protected final static int TOTAL_PAGES = 65536;
56       protected final static int BRK_LIMIT = 32768;
57       // Top page is always empty
58       // next page down contains command line arguments
59       protected final static int ARGS_ADDR = (TOTAL_PAGES-2)*PAGE_SIZE;
60       // next page down contains _user_info data
61       protected final static int USER_INFO_ADDR = (TOTAL_PAGES-3)*PAGE_SIZE;
62       // next page down is the start of the stack
63       protected final static int INITIAL_SP = (TOTAL_PAGES-3)*PAGE_SIZE;
64       // magic page that signified an allocated but empty (untouched) page
65       private final static int[] emptyPage = new int[0];
66       
67       // Main memory
68       protected final int[][] readPages;
69       protected final int[][] writePages;
70       
71       // Brk
72       protected int brk; // PAGE not address
73           
74       // Entry point - what start() sets pc to
75       protected int entryPoint;
76       
77       // State constants
78       public final static int UNINITIALIZED = 0;
79       public final static int INITIALIZED = 1;
80       public final static int RUNNING = 2;
81       public final static int PAUSED = 3;
82       public final static int DONE = 4;
83       
84       // State
85       protected int state = UNINITIALIZED;
86       public final int getState() { return state; }
87       protected int exitStatus;
88       
89       // File descriptors
90       private final static int OPEN_MAX = 256;
91       private FileDescriptor[] fds;
92       
93       // Temporary buffer for read/write operations
94       private byte[] _byteBuf = null;
95       private final static int MAX_CHUNK = 4*1024*1024-8;
96       
97       // Abstract methods
98       // This should start executing at pc
99       public abstract void execute() throws EmulationException;
100      // This should initialize the cpu registers to point to the entry point
101      protected abstract void _start(int pc);
102     
103      public static final int PID = 1;
104      
105      public VM() {
106          readPages = new int[TOTAL_PAGES][];
107          writePages = new int[TOTAL_PAGES][];
108          for(int i=0;i<STACK_PAGES;i++)
109              readPages[TOTAL_PAGES-1-i] = writePages[TOTAL_PAGES-1-i] = emptyPage;
110      }
111      
112      public void copyin(int addr, byte[] a, int length) throws ReadFaultException {
113          int n=0;
114          if((addr&3)!=0) {
115              int word = memRead(addr&~3);
116               switch(addr&3) {
117                  case 1: a[n++] = (byte)((word>>>16)&0xff); if(length-n==0) break;
118                  case 2: a[n++] = (byte)((word>>> 8)&0xff); if(length-n==0) break;
119                  case 3: a[n++] = (byte)((word>>> 0)&0xff); if(length-n==0) break;
120              }
121              addr = (addr&~3)+4;
122          }
123          while(length-n > 3) {
124              int start = (addr&(PAGE_SIZE-1))>>2;
125              int end = start + (min(PAGE_SIZE-(addr&(PAGE_SIZE-1)),(length-n)&~3) >> 2);
126              int[] page = readPages[addr >>> PAGE_SHIFT];
127              if(page == null) throw new ReadFaultException(addr);
128              if(page == emptyPage) { addr+=(end-start)<<2; n+=(end-start)<<2; continue; }
129              for(int i=start;i<end;i++,addr+=4) {
130                  int word = page[i];
131                  a[n++] = (byte)((word>>>24)&0xff); a[n++] = (byte)((word>>>16)&0xff);
132                  a[n++] = (byte)((word>>> 8)&0xff); a[n++] = (byte)((word>>> 0)&0xff);
133              }
134          }
135          if(length-n > 0) {
136              int word = memRead(addr);
137              if(length-n >= 1) a[n] = (byte)((word>>>24)&0xff);
138              if(length-n >= 2) a[n+1] = (byte)((word>>>16)&0xff);
139              if(length-n >= 3) a[n+2] = (byte)((word>>> 8)&0xff);
140          }
141      }
142      
143      public void copyout(byte[] a, int addr, int length) throws FaultException {
144          int n=0;
145          if((addr&3)!=0) {
146              int word = memRead(addr&~3);
147               switch(addr&3) {
148                  case 1: word = (word&0xff00ffff)|((a[n]&0xff)<<16); n++; if(length-n==0) break;
149                  case 2: word = (word&0xffff00ff)|((a[n]&0xff)<< 8); n++; if(length-n==0) break;
150                  case 3: word = (word&0xffffff00)|((a[n]&0xff)<< 0); n++; if(length-n==0) break;
151              }
152              memWrite(addr&~3,word);
153              addr = (addr&~3)+4;
154          }
155          
156          while(length-n > 3) {
157              int start = (addr&(PAGE_SIZE-1))>>2;
158              int end = start + (min(PAGE_SIZE-(addr&(PAGE_SIZE-1)),(length-n)&~3) >> 2);
159              int[] page = writePages[addr >>> PAGE_SHIFT];
160              if(page == null) throw new WriteFaultException(addr);
161              if(page == emptyPage) { memWrite(addr,0); page = writePages[addr >>> PAGE_SHIFT]; }
162              for(int i=start;i<end;i++,addr+=4) {
163                  int word = ((a[n+0]&0xff)<<24)|((a[n+1]&0xff)<<16)|((a[n+2]&0xff)<<8)|((a[n+3]&0xff)<<0); n+=4;
164                  page[i] = word;
165              }
166          }
167          if(length-n > 0) {
168              int word = memRead(addr);
169              word = (word&0x00ffffff)|((a[n]&0xff)<<24);
170              if(length-n > 1) { word = (word&0xff00ffff)|((a[n+1]&0xff)<<16); }
171              if(length-n > 2) { word = (word&0xffff00ff)|((a[n+2]&0xff)<< 8); }
172              memWrite(addr,word);
173          }
174      }
175      
176      public final int memRead(int addr) throws ReadFaultException  {
177          if((addr & 3) != 0) throw new ReadFaultException(addr);
178          int page = addr >>> PAGE_SHIFT;
179          int entry = (addr >>> 2) & (PAGE_WORDS-1);
180          try {
181              return readPages[page][entry];
182          } catch(ArrayIndexOutOfBoundsException e) {
183              if(page < 0) throw e; // should never happen
184              if(page > readPages.length) throw new ReadFaultException(addr);
185              if(readPages[page] != emptyPage) throw e; // should never happen
186              initPage(page);
187              return 0;
188          } catch(NullPointerException e) {
189              throw new ReadFaultException(addr);
190          }
191      }
192      
193      protected final void memWrite(int addr, int value) throws WriteFaultException  {
194          if((addr & 3) != 0) throw new WriteFaultException(addr);
195          int page = addr >>> PAGE_SHIFT;
196          int entry = (addr>>>2)&(PAGE_WORDS-1);
197          try {
198              writePages[page][entry] = value;
199          } catch(ArrayIndexOutOfBoundsException e) {
200              if(page < 0) throw e;// should never happen
201              if(page > writePages.length) throw new WriteFaultException(addr);
202              if(readPages[page] != emptyPage) throw e; // should never happen
203              initPage(page);
204              writePages[page][entry] = value;
205          } catch(NullPointerException e) {
206              throw new WriteFaultException(addr);
207          }
208      }
209      
210      protected void initPage(int page) { writePages[page] = readPages[page] = new int[PAGE_WORDS]; }
211      
212      public final int exitStatus() {
213          if(state != DONE) throw new IllegalStateException("exitStatus() called in an inappropriate state");
214          return exitStatus;
215      }
216       
217      public final int run(String[] args) throws EmulationException {
218          start(args);
219          for(;;) {
220              execute();
221              if(state != PAUSED) break;
222              System.err.println("WARNING: Pause requested while executing run()");
223              try { Thread.sleep(500); } catch(InterruptedException e) { }
224          }
225          if(state != DONE) throw new IllegalStateException("run() ended up in an inappropriate state");
226          return exitStatus();
227      }
228      
229      private void addArgs(String[] args) throws EmulationException {
230          if(state == UNINITIALIZED || state == RUNNING || state == PAUSED) throw new IllegalStateException("addArgs() called in inappropriate state");
231          int count = args.length;
232          byte[] nullTerminator = new byte[1];
233          int total = 4; /* null last table entry  */
234          for(int i=0;i<count;i++) total += args[i].length() + 1/*null terminator*/ + 4/*table entry*/;
235          if(total > PAGE_SIZE) throw new EmulationException("Arguments too large");
236          int start = ARGS_ADDR;
237          int addr = start + (count+1)*4;
238          int[] table = new int[count+1];
239          for(int i=0;i<count;i++) {
240              byte[] a;
241              try { a = args[i].getBytes("US-ASCII"); } catch(UnsupportedEncodingException e){ throw  new Error(e.getMessage()); }
242              table[i] = addr;
243  
244                  copyout(a,addr,a.length);
245                  addr += a.length;
246                  copyout(nullTerminator,addr,1);
247                  addr += 1;
248  
249          }
250          addr=start;
251          for(int i=0;i<count;i++) {
252              memWrite(addr,table[i]);
253              addr += 4;
254          }
255      }
256      
257      public void setUserInfo(int index, int word) throws EmulationException {
258          if(index < 0 ||  index >= 1024) throw new EmulationException("setUserInfo called with index >= 1024");
259          memWrite(USER_INFO_ADDR+index*4,word);
260      }
261      
262      public int getUserInfo(int index) throws EmulationException {
263          if(index < 0 ||  index >= 1024) throw new EmulationException("getUserInfo called with index >= 1024");
264          return memRead(USER_INFO_ADDR+index*4);
265      }
266      
267      public final void start(String[] args) throws EmulationException {
268          if(state == UNINITIALIZED || state == RUNNING || state == PAUSED) throw new IllegalStateException("start() called in inappropriate state");
269          _start(entryPoint);
270          addArgs(args);
271          fds = new FileDescriptor[OPEN_MAX];
272          fds[0] = new InputStreamFD(System.in)   { public boolean isatty() { return true; } };
273          fds[1] = new OutputStreamFD(System.out) { public boolean isatty() { return true; } };
274          fds[2] = new OutputStreamFD(System.err) { public boolean isatty() { return true; } };
275          state = PAUSED;
276      }
277      
278          
279      // Syscalls
280      private int write(int fdn, int addr, int count) {
281          int n = 0;
282          int r;
283          FileDescriptor fd;
284          count = Math.min(count,MAX_CHUNK);
285          try {
286              fd = fds[fdn];
287              if(fd == null || !fd.writable()) return -EBADFD;
288          } catch(ArrayIndexOutOfBoundsException e) {
289              return -EBADFD;
290          }
291          try {
292              byte[] buf = byteBuf(count);
293              copyin(addr,buf,count);
294              return fd.write(buf,0,count);
295          } catch(FaultException e) {
296              System.err.println(e);
297              return -EFAULT;
298          } catch(IOException e) {
299              System.err.println(e);
300              return -EIO;
301          }
302      }
303  
304      private int read(int fdn, int addr, int count) {
305          FileDescriptor fd;
306          count = Math.min(count,MAX_CHUNK);
307          try {
308              fd = fds[fdn];
309              if(fd == null || !fd.readable()) return -EBADFD;
310          } catch(ArrayIndexOutOfBoundsException e) {
311              return -EBADFD;
312          }
313          try {
314              byte[] buf = byteBuf(count);
315              int n = fd.read(buf,0,count);
316              copyout(buf,addr,n);
317              return n;
318          } catch(FaultException e) {
319              System.err.println(e);
320              return -EFAULT;
321          } catch(IOException e) {
322              System.err.println(e);
323              return -EIO;
324          }
325      }
326      
327      private int close(int fdn) {
328          FileDescriptor fd;
329          try {
330              fd = fds[fdn];
331              if(fd == null) return -EBADFD;
332          } catch(ArrayIndexOutOfBoundsException e) {
333              return -EBADFD;
334          }
335          fds[fdn] = null;
336          fd.close();
337          return 0;
338      }
339      
340      private int stat(FileInfo fi, int addr) {
341          int size = fi.size();
342          try {
343              memWrite(addr+0,0); // st_dev (top 16), // st_ino (bottom 16)
344              memWrite(addr+4,(fi.type() & 0xf000)|0644); // st_mode
345              memWrite(addr+8,1); // st_nlink (top 16) // st_uid (bottom 16)
346              memWrite(addr+12,0); // st_gid (top 16) // st_rdev (bottom 16)
347              memWrite(addr+16,size); // st_size
348              memWrite(addr+20,0); // st_atime
349              // memWrite(addr+24,0) // st_spare1
350              memWrite(addr+28,(int)(fi.modTime()/1000)); // st_mtime
351              // memWrite(addr+32,0) // st_spare2
352              memWrite(addr+36,0); // st_atime
353              // memWrite(addr+40,0) // st_spare3
354              memWrite(addr+44,512); // st_bklsize;
355              memWrite(addr+48,(size+511)&(~511)); // st_blocks
356              // memWrite(addr+52,0) // st_spare4[0]
357              // memWrite(addr+56,0) // st_spare4[1]
358          } catch(FaultException e) {
359              System.err.println(e);
360              return -EFAULT;
361          }
362          return 0;
363      }
364      
365      private int fstat(int fdn, int addr) {
366          FileDescriptor fd;
367          try {
368              fd = fds[fdn];
369              if(fd == null) return -EBADFD;
370          } catch(ArrayIndexOutOfBoundsException e) {
371              return -EBADFD;
372          }
373          return stat(fd.fileInfo(),addr);
374      }
375      
376      public int sbrk(int incr) {
377          if(incr==0) return brk<<PAGE_SHIFT;
378          int oldBrk = brk;
379          int newBrk = oldBrk + ((incr+PAGE_SIZE-1)>>PAGE_SHIFT);
380          if(newBrk >= BRK_LIMIT) {
381              System.err.println("Hit BRK_LIMIT");
382              return -ENOMEM;
383          }
384          for(int i=oldBrk;i<newBrk+256;i++)
385              readPages[i] = writePages[i] = emptyPage;
386          brk = newBrk;
387          return oldBrk<<PAGE_SHIFT;
388      }
389          
390      private int open(int addr, int flags, int mode) {
391          final int O_RDONLY = 0;
392          final int O_WRONLY = 1;
393          final int O_RDWR = 2;
394          final int O_APPEND = 0x0008;
395          final int O_CREAT = 0x0200;
396          final int O_NONBLOCK = 0x4000;
397          final int O_EXCL = 0x0800;
398          
399          if((flags & O_APPEND) != 0) {
400              System.err.println("WARNING: O_APPEND not supported");
401              return -EOPNOTSUPP;
402          }
403          if((flags & O_NONBLOCK) != 0) {
404              System.err.println("WARNING: O_NONBLOCK not supported");
405              return -EOPNOTSUPP;
406          }
407          
408          try {
409              int fdn=-1;
410              File f = new File(cstring(addr));
411              System.err.println("Opening: " + f);
412              if((flags & O_EXCL) != 0 && (flags & O_CREAT) != 0)
413                  if(!f.createNewFile()) return -EEXIST;
414              if(f.exists()) {
415                  if(f.length() >= Integer.MAX_VALUE) return -EOPNOTSUPP;
416              } else {
417                  if((flags & O_CREAT) == 0) return -ENOENT;
418              }
419              for(int i=0;i<OPEN_MAX;i++) if(fds[i] == null) { fdn = i; break; }
420              if(fdn==-1) return -ENFILE;
421              fds[fdn] = new RegularFileDescriptor(f,flags&3);
422              return fdn;
423          } catch(FaultException e) {
424              return -EFAULT;
425          } catch(FileNotFoundException e) { 
426              if(e.getMessage().indexOf("Permission denied") >= 0) return -EACCES;
427              return -ENOENT;
428          } catch(IOException e) {
429              return -EIO;
430          }
431      }
432      
433      private int seek(int fdn, int offset, int whence) {
434          FileDescriptor fd;
435          try {
436              fd = fds[fdn];
437              if(fd == null || !fd.readable()) return -EBADFD;
438          } catch(ArrayIndexOutOfBoundsException e) {
439              return -EBADFD;
440          }
441          try {
442              return fd.seek(offset,whence);
443          } catch(IOException e) {
444              System.err.println(e);
445              return -EPIPE;
446          }
447      }
448      
449      // This will only be called by raise() to invoke the default handler
450      // We don't have to worry about actually delivering the signal
451      private int kill(int pid, int signal) {
452          if(pid != PID) return -ESRCH;
453          if(signal < 0 || signal >= 32) return -EINVAL;
454          switch(signal) {
455              case 0: return 0;
456              case 17: // SIGSTOP
457              case 18: // SIGTSTP
458              case 21: // SIGTTIN
459              case 22: // SIGTTOU
460                  state = PAUSED;
461                  break;
462              case 19: // SIGCONT
463              case 20: // SIGCHLD
464              case 23: // SIGIO
465              case 28: // SIGWINCH
466                  break;
467              default: {
468                  String msg = "Terminating on signal: " + signal + "\n";
469                  exitStatus = 1;
470                  state = DONE;
471                  if(fds[2]==null) {
472                      System.out.print(msg);
473                  } else {
474                      byte[] b = msg.getBytes();
475                      try {
476                          fds[2].write(b,0,b.length);
477                      } catch(IOException e) { }
478                  }
479              }
480          }
481          return 0;
482      }
483      
484      private int getpid() { return PID; }
485      
486      protected int syscall(int syscall, int a, int b, int c, int d) {
487          switch(syscall) {
488              case SYS_null: return 0;
489              case SYS_exit: exitStatus = a; state = DONE; return 0;
490              case SYS_pause: state = PAUSED; return 0;
491              case SYS_write: return write(a,b,c);
492              case SYS_fstat: return fstat(a,b);
493              case SYS_sbrk: return sbrk(a);
494              case SYS_open: return open(a,b,c);
495              case SYS_close: return close(a);
496              case SYS_read: return read(a,b,c);
497              case SYS_seek: return seek(a,b,c);
498              case SYS_kill: return kill(a,b);
499              case SYS_getpid: return getpid();
500              default:
501                  System.err.println("Attempted to use unknown syscall: " + syscall);
502                  return -ENOSYS;
503          }
504      }
505      
506      // Helper function to read a cstring from main memory
507      public String cstring(int addr) throws ReadFaultException {
508          StringBuffer sb = new StringBuffer();
509          for(;;) {
510              int word = memRead(addr&~3);
511              switch(addr&3) {
512                  case 0: if(((word>>>24)&0xff)==0) return sb.toString(); sb.append((char)((word>>>24)&0xff)); addr++;
513                  case 1: if(((word>>>16)&0xff)==0) return sb.toString(); sb.append((char)((word>>>16)&0xff)); addr++;
514                  case 2: if(((word>>> 8)&0xff)==0) return sb.toString(); sb.append((char)((word>>> 8)&0xff)); addr++;
515                  case 3: if(((word>>> 0)&0xff)==0) return sb.toString(); sb.append((char)((word>>> 0)&0xff)); addr++;
516              }
517          }
518      }
519       
520      // Exceptions
521      public static class ReadFaultException extends FaultException {
522          public ReadFaultException(int addr) { super(addr); }
523      }
524      public static class WriteFaultException extends FaultException {
525          public WriteFaultException(int addr) { super(addr); }
526      }
527      public static abstract class FaultException extends EmulationException {
528          private int addr;
529          public FaultException(int addr) { this.addr = addr; }
530          public String getMessage() { return "fault at: " + toHex(addr); }
531      }
532      public static class EmulationException extends Exception {
533          public EmulationException() { }
534          public EmulationException(String s) { super(s); }
535      }
536      
537      // FileInfo classes - used by stat(2)
538      static class FileInfo {
539          public static final int S_IFIFO = 0010000;
540          public static final int S_FCHR =  0020000;
541          public static final int S_IFDIR = 0040000;
542          public static final int S_IFREG = 0100000;
543          
544          public int size() { return 0; }
545          public int type() { return S_IFIFO; }
546          public long modTime() { return 0; }
547      }
548          
549      public static class FileFileInfo extends FileInfo {
550          public File f;
551          public FileFileInfo(File f) { this.f = f; }
552          public int size() { return (int)f.length(); }
553          public int type() { return f.isDirectory() ? S_IFDIR : S_IFREG; }
554          public long modTime() { return f.lastModified(); }
555      }
556  
557      // File descriptor classes
558      public static abstract class FileDescriptor {
559          public boolean readable() { return false; }
560          public boolean writable() { return false; }
561          
562          private static final FileInfo nullFi = new FileInfo();
563          private FileInfo fi;
564          public FileInfo fileInfo() { return fi; }
565          
566          FileDescriptor() { this(null); }
567          FileDescriptor(FileInfo fi) { this.fi = fi==null ? nullFi : fi; }
568          
569          public int read(byte[] a, int off, int length) throws IOException { throw new IOException("no definition"); }
570          public int write(byte[] a, int off, int length) throws IOException { throw new IOException("no definition"); }
571          
572          public int seek(int n, int whence)  throws IOException  { return -ESPIPE; }
573          public boolean isatty() { return false; }
574          
575          void close() { }
576      }
577      
578      public static class RegularFileDescriptor extends FileDescriptor {
579          private int mode;
580          private RandomAccessFile raf;
581          public boolean readable() { return mode != 1; }
582          public boolean writable() { return mode != 0; }
583          
584          RegularFileDescriptor(File f,int m) throws IOException {
585              super(new FileFileInfo(f));
586              String mode = m == 0 ? "r" : "rw";
587              this.mode = m;
588              raf = new RandomAccessFile(f,mode);
589              if(raf.length() >= Integer.MAX_VALUE) throw new IOException("File too large");
590          }
591          
592          public int seek(int n, int whence) throws IOException {
593              final int SEEK_SET = 0;
594              final int SEEK_CUR = 1;
595              final int SEEK_END = 2;
596              
597              switch(whence) {
598                  case SEEK_SET: break;
599                  case SEEK_CUR: n = (int)(raf.getFilePointer()+n); break;
600                  case SEEK_END: n = (int)(raf.length()+n); break;
601                  default: return -EINVAL;
602              }
603              raf.seek(n);
604              return n;
605          }
606          
607          public int write(byte[] a, int off, int length) throws IOException { raf.write(a,off,length); return length; }
608          public int read(byte[] a, int off, int length) throws IOException { int n = raf.read(a,off,length); return n < 0 ? 0 : n; }
609          
610          void close() { try { raf.close(); } catch(Exception e) { } }
611      }
612      
613      public class OutputStreamFD extends FileDescriptor {
614          private OutputStream os;
615          public boolean writable() { return true; }
616          public OutputStreamFD(OutputStream os) { this.os = os; }
617          public int write(byte[] a, int off, int length) throws IOException { os.write(a,off,length); return length; }
618      }
619      
620      public class InputStreamFD extends FileDescriptor {
621          private InputStream is;
622          public boolean readable() { return true; }
623          public InputStreamFD(InputStream is) { this.is = is; }
624          public int read(byte[] a, int off, int length) throws IOException { int n = is.read(a,off,length); return n < 0 ? 0 : n; }
625      }
626      
627      // Utility functions
628      private byte[] byteBuf(int size) {
629          if(_byteBuf==null) _byteBuf = new byte[size];
630          else if(_byteBuf.length < size)
631              _byteBuf = new byte[min(max(_byteBuf.length*2,size),MAX_CHUNK+8)];
632          return _byteBuf;
633      }
634      protected final static String toHex(int n) { return "0x" + Long.toString(n & 0xffffffffL, 16); }
635      protected final static int min(int a, int b) { return a < b ? a : b; }
636      protected final static int max(int a, int b) { return a > b ? a : b; }
637  }
638  
639  
640  
641  interface Errno {
642      public static final int EPERM = 1;
643      public static final int ENOENT = 2;
644      public static final int ESRCH = 3;
645      public static final int EINTR = 4;
646      public static final int EIO = 5;
647      public static final int ENXIO = 6;
648      public static final int ENOEXEC = 8;
649      public static final int EBADF = 9;
650      public static final int ECHILD = 10;
651      public static final int EAGAIN = 11;
652      public static final int ENOMEM = 12;
653      public static final int EACCES = 13;
654      public static final int EFAULT = 14;
655      public static final int ENOTBLK = 15;
656      public static final int EBUSY = 16;
657      public static final int EEXIST = 17;
658      public static final int EXDEV = 18;
659      public static final int ENODEV = 19;
660      public static final int ENOTDIR = 20;
661      public static final int EISDIR = 21;
662      public static final int EINVAL = 22;
663      public static final int ENFILE = 23;
664      public static final int EMFILE = 24;
665      public static final int ENOTTY = 25;
666      public static final int ETXTBSY = 26;
667      public static final int EFBIG = 27;
668      public static final int ENOSPC = 28;
669      public static final int ESPIPE = 29;
670      public static final int EROFS = 30;
671      public static final int EMLINK = 31;
672      public static final int EPIPE = 32;
673      public static final int EDOM = 33;
674      public static final int ERANGE = 34;
675      public static final int ENOMSG = 35;
676      public static final int EIDRM = 36;
677      public static final int ECHRNG = 37;
678      public static final int ELNRNG = 41;
679      public static final int EUNATCH = 42;
680      public static final int ENOCSI = 43;
681      public static final int EDEADLK = 45;
682      public static final int ENOLCK = 46;
683      public static final int EBADE = 50;
684      public static final int EBADR = 51;
685      public static final int EXFULL = 52;
686      public static final int ENOANO = 53;
687      public static final int EBADRQC = 54;
688      public static final int EBADSLT = 55;
689      public static final int EDEADLOCK = 56;
690      public static final int EBFONT = 57;
691      public static final int ENOSTR = 60;
692      public static final int ENODATA = 61;
693      public static final int ETIME = 62;
694      public static final int ENOSR = 63;
695      public static final int ENONET = 64;
696      public static final int ENOPKG = 65;
697      public static final int EREMOTE = 66;
698      public static final int ENOLINK = 67;
699      public static final int EADV = 68;
700      public static final int ESRMNT = 69;
701      public static final int ECOMM = 70;
702      public static final int EPROTO = 71;
703      public static final int EMULTIHOP = 74;
704      public static final int ELBIN = 75;
705      public static final int EDOTDOT = 76;
706      public static final int EBADMSG = 77;
707      public static final int EFTYPE = 79;
708      public static final int ENOTUNIQ = 80;
709      public static final int EBADFD = 81;
710      public static final int EREMCHG = 82;
711      public static final int ELIBACC = 83;
712      public static final int ELIBBAD = 84;
713      public static final int ELIBSCN = 85;
714      public static final int ELIBMAX = 86;
715      public static final int ELIBEXEC = 87;
716      public static final int ENOSYS = 88;
717      public static final int ENMFILE = 89;
718      public static final int ENOTEMPTY = 90;
719      public static final int ENAMETOOLONG = 91;
720      public static final int ELOOP = 92;
721      public static final int EOPNOTSUPP = 95;
722      public static final int EPFNOSUPPORT = 96;
723      public static final int ECONNRESET = 104;
724      public static final int ENOBUFS = 105;
725      public static final int EAFNOSUPPORT = 106;
726      public static final int EPROTOTYPE = 107;
727      public static final int ENOTSOCK = 108;
728      public static final int ENOPROTOOPT = 109;
729      public static final int ESHUTDOWN = 110;
730      public static final int ECONNREFUSED = 111;
731      public static final int EADDRINUSE = 112;
732      public static final int ECONNABORTED = 113;
733      public static final int ENETUNREACH = 114;
734      public static final int ENETDOWN = 115;
735      public static final int ETIMEDOUT = 116;
736      public static final int EHOSTDOWN = 117;
737      public static final int EHOSTUNREACH = 118;
738      public static final int EINPROGRESS = 119;
739      public static final int EALREADY = 120;
740      public static final int EDESTADDRREQ = 121;
741      public static final int EMSGSIZE = 122;
742      public static final int EPROTONOSUPPORT = 123;
743      public static final int ESOCKTNOSUPPORT = 124;
744      public static final int EADDRNOTAVAIL = 125;
745      public static final int ENETRESET = 126;
746      public static final int EISCONN = 127;
747      public static final int ENOTCONN = 128;
748      public static final int ETOOMANYREFS = 129;
749      public static final int EPROCLIM = 130;
750      public static final int EUSERS = 131;
751      public static final int EDQUOT = 132;
752      public static final int ESTALE = 133;
753      public static final int ENOTSUP = 134;
754      public static final int ENOMEDIUM = 135;
755      public static final int ENOSHARE = 136;
756      public static final int ECASECLASH = 137;
757      public static final int EILSEQ = 138;
758      public static final int EOVERFLOW = 139;
759      public static final int __ELASTERROR = 2000;
760  }
761  
762  interface Syscalls {
763      public static final int SYS_null = 0;
764      public static final int SYS_exit = 1;
765      public static final int SYS_pause = 2;
766      public static final int SYS_open = 3;
767      public static final int SYS_close = 4;
768      public static final int SYS_read = 5;
769      public static final int SYS_write = 6;
770      public static final int SYS_sbrk = 7;
771      public static final int SYS_fstat = 8;
772      public static final int SYS_isatty = 9;
773      public static final int SYS_seek = 10;
774      public static final int SYS_kill = 11;
775      public static final int SYS_getpid = 12;
776  }
777