github.com/gotranspile/cxgo@v0.3.7/runtime/stdio/stdio.go (about)

     1  package stdio
     2  
     3  import (
     4  	"io"
     5  	"log"
     6  	"os"
     7  	"strings"
     8  	"unsafe"
     9  
    10  	"github.com/gotranspile/cxgo/runtime/libc"
    11  )
    12  
    13  const (
    14  	defPermFile = 0644
    15  )
    16  
    17  const (
    18  	EOF      = -2
    19  	SEEK_SET = int32(io.SeekStart)
    20  	SEEK_CUR = int32(io.SeekCurrent)
    21  	SEEK_END = int32(io.SeekEnd)
    22  )
    23  
    24  func Stdout() *File {
    25  	return defaultFS.OpenFrom(defaultFS.fs.Stdout())
    26  }
    27  
    28  func Stderr() *File {
    29  	return defaultFS.OpenFrom(defaultFS.fs.Stderr())
    30  }
    31  
    32  func Stdin() *File {
    33  	return defaultFS.OpenFrom(defaultFS.fs.Stdin())
    34  }
    35  
    36  func Remove(path string, _ ...interface{}) int {
    37  	panic("TODO")
    38  }
    39  
    40  func Rename(path1, path2 string, _ ...interface{}) int {
    41  	panic("TODO")
    42  }
    43  
    44  func openFlags(mode string) int {
    45  	mode = strings.ReplaceAll(mode, "b", "")
    46  	switch mode {
    47  	case "r": // open file for reading
    48  		return os.O_RDONLY
    49  	case "w": // truncate to zero length or create file for writing
    50  		return os.O_CREATE | os.O_TRUNC | os.O_WRONLY
    51  	case "a": // append; open or create file for writing at end-of-file
    52  		return os.O_CREATE | os.O_APPEND | os.O_WRONLY
    53  	case "r+": // open file for update (reading and writing)
    54  		return os.O_RDWR
    55  	case "w+": // truncate to zero length or create file for update
    56  		return os.O_CREATE | os.O_TRUNC | os.O_RDWR
    57  	case "a+": // append; open or create file for update, writing at end-of-file
    58  		return os.O_CREATE | os.O_APPEND | os.O_RDWR
    59  	default:
    60  		panic("unknown file mode: " + mode)
    61  	}
    62  }
    63  
    64  func FOpen(path, mode string) *File {
    65  	return defaultFS.OpenS(path, mode)
    66  }
    67  
    68  func OpenFrom(f FileI) *File {
    69  	return defaultFS.OpenFrom(f)
    70  }
    71  
    72  func (fs *filesystem) OpenFrom(f FileI) *File {
    73  	ff := &File{
    74  		fs:   fs,
    75  		file: f,
    76  		fd:   f.Fd(),
    77  	}
    78  	fs.Lock()
    79  	fs.byFD[ff.fd] = ff
    80  	fs.Unlock()
    81  	return ff
    82  }
    83  
    84  func (fs *filesystem) Open(path string, flag int) *File {
    85  	f, err := fs.fs.Open(path, flag, defPermFile)
    86  	log.Printf("fopen(%q, %v): %v", path, flag, err)
    87  	if err != nil {
    88  		libc.SetErr(err)
    89  		return nil
    90  	}
    91  	return fs.OpenFrom(f)
    92  }
    93  
    94  func (fs *filesystem) OpenS(path, mode string) *File {
    95  	flags := openFlags(mode)
    96  	return fs.Open(path, flags)
    97  }
    98  
    99  func FDOpen(fd uintptr, mode string) *File {
   100  	f := ByFD(fd)
   101  	log.Printf("fdopen(%d, %q): %v", fd, mode, f)
   102  	if f == nil {
   103  		return nil
   104  	}
   105  	flags := openFlags(mode)
   106  	_ = flags // FIXME: use flags
   107  	return f
   108  }
   109  
   110  func FDOpenS(fd uintptr, mode string) *File {
   111  	f := ByFD(fd)
   112  	log.Printf("fdopen(%d, %q): %v", fd, mode, f)
   113  	if f == nil {
   114  		return nil
   115  	}
   116  	flags := openFlags(mode)
   117  	_ = flags // FIXME: use flags
   118  	return f
   119  }
   120  
   121  func FReOpen(path, mode string, f *File) *File {
   122  	panic("TODO")
   123  }
   124  
   125  func Fscanf(file *File, format string, args ...interface{}) int {
   126  	n, err := FscanfGo(file.file, format, args...)
   127  	if err != nil {
   128  		file.err = err
   129  		return -1
   130  	}
   131  	return n
   132  }
   133  
   134  func Vfscanf(file *File, format string, args libc.ArgList) int {
   135  	return Fscanf(file, format, args.Args()...)
   136  }
   137  
   138  type File struct {
   139  	fs   *filesystem
   140  	fd   uintptr
   141  	file FileI
   142  	err  error
   143  	c    *int
   144  }
   145  
   146  func (f *File) SetErr(err error) {
   147  	f.err = err
   148  }
   149  
   150  func (f *File) IsEOF() int32 {
   151  	if f.err == io.EOF {
   152  		return 1
   153  	}
   154  	return 0
   155  }
   156  
   157  func (f *File) Error() int64 {
   158  	if f.err == nil {
   159  		return 0
   160  	}
   161  	return int64(libc.ErrCode(f.err))
   162  }
   163  
   164  func (f *File) FileNo() uintptr {
   165  	return f.fd
   166  }
   167  
   168  func (f *File) Flush() int32 {
   169  	err := f.file.Sync()
   170  	if err != nil {
   171  		f.err = err
   172  		return -1
   173  	}
   174  	return 0
   175  }
   176  
   177  func (f *File) Close() int32 {
   178  	if f == nil {
   179  		return -1
   180  	}
   181  	if err := f.file.Close(); err != nil {
   182  		f.err = err
   183  	}
   184  	f.fs.Lock()
   185  	delete(f.fs.byFD, f.fd)
   186  	f.fs.Unlock()
   187  	return 0 // TODO
   188  }
   189  
   190  func (f *File) WriteN(p *byte, size, cnt int) int32 {
   191  	n := f.Write(p, size*cnt)
   192  	if n > 0 {
   193  		n /= int32(size)
   194  	}
   195  	return n
   196  }
   197  
   198  func (f *File) Write(p *byte, sz int) int32 {
   199  	if f == nil {
   200  		return -1
   201  	}
   202  	n, err := f.file.Write(unsafe.Slice(p, sz))
   203  	if err != nil {
   204  		f.err = err
   205  	}
   206  	return int32(n)
   207  }
   208  
   209  func (f *File) ReadN(p *byte, size, cnt int) int32 {
   210  	n := f.Read(p, size*cnt)
   211  	if n > 0 {
   212  		n /= int32(size)
   213  	}
   214  	return n
   215  }
   216  
   217  func (f *File) Read(p *byte, sz int) int32 {
   218  	if f == nil {
   219  		return -1
   220  	} else if sz == 0 {
   221  		return 0
   222  	}
   223  	n, err := f.file.Read(unsafe.Slice(p, sz))
   224  	if err != nil {
   225  		f.err = err
   226  	}
   227  	return int32(n)
   228  }
   229  
   230  func (f *File) GetC() int {
   231  	if f.c != nil {
   232  		c := *f.c
   233  		f.c = nil
   234  		return c
   235  	}
   236  	var b [1]byte
   237  	_, err := f.file.Read(b[:])
   238  	if err != nil {
   239  		//log.Printf("fgetc(): %v", err)
   240  		f.err = err
   241  		if err == io.EOF {
   242  			return EOF
   243  		}
   244  		return -1
   245  	}
   246  	return int(b[0])
   247  }
   248  
   249  func (f *File) UnGetC(c int) int {
   250  	f.c = &c
   251  	return 0
   252  }
   253  
   254  func (f *File) GetS(buf *byte, sz int32) *byte {
   255  	dst := unsafe.Slice(buf, int(sz))
   256  	var b [1]byte
   257  	for len(dst) > 1 {
   258  		_, err := f.file.Read(b[:])
   259  		if err != nil {
   260  			log.Printf("fgets(%q, %d): %v", f.file.Name(), sz, err)
   261  			f.err = err
   262  			return nil
   263  		}
   264  		dst[0] = b[0]
   265  		dst = dst[1:]
   266  		if b[0] == '\n' {
   267  			break
   268  		}
   269  	}
   270  	dst[0] = 0
   271  	return buf
   272  }
   273  
   274  func (f *File) PutC(c int) int64 {
   275  	if f == nil {
   276  		return -1
   277  	}
   278  	if c < 0 || c > 0xff {
   279  		panic("TODO")
   280  	}
   281  	n, err := f.file.Write([]byte{byte(c)})
   282  	if err != nil {
   283  		f.err = err
   284  	}
   285  	return int64(n)
   286  }
   287  
   288  func (f *File) PutS(s *byte) int64 {
   289  	return int64(f.Write(s, libc.StrLen(s)))
   290  }
   291  
   292  func (f *File) Scanf(format string, args ...interface{}) int64 {
   293  	panic("TODO")
   294  }
   295  
   296  func (f *File) Tell() int64 {
   297  	cur, err := f.file.Seek(0, io.SeekCurrent)
   298  	if err != nil {
   299  		libc.SetErr(err)
   300  		f.err = err
   301  		return -1
   302  	}
   303  	return cur
   304  }
   305  
   306  func (f *File) Seek(off int64, whence int32) int32 {
   307  	_, err := f.file.Seek(off, int(whence))
   308  	if err != nil {
   309  		f.err = err
   310  		return -1
   311  	}
   312  	return 0
   313  }