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 }