/* Copyright 2015 Wolfgang Thaller. This file is part of Retro68. Retro68 is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Retro68 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Under Section 7 of GPL version 3, you are granted additional permissions described in the GCC Runtime Library Exception, version 3.1, as published by the Free Software Foundation. You should have received a copy of the GNU General Public License and a copy of the GCC Runtime Library Exception along with this program; see the files COPYING and COPYING.RUNTIME respectively. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include void *_sbrk_r(struct _reent *reent, ptrdiff_t increment) { Debugger(); return NewPtrClear(increment); } void _exit(int status) { //if(status != 0) // Debugger(); ExitToShell(); for(;;) ; } ssize_t _consolewrite(int fd, const void *buf, size_t count); ssize_t _consoleread(int fd, void *buf, size_t count); const int kMacRefNumOffset = 10; ssize_t _write_r(struct _reent *reent, int fd, const void *buf, size_t count) { long cnt = count; if(fd >= kMacRefNumOffset) { FSWrite(fd - kMacRefNumOffset, &cnt, buf); return cnt; } else return _consolewrite(fd,buf,count); } ssize_t _read_r(struct _reent *reent, int fd, void *buf, size_t count) { long cnt = count; if(fd >= kMacRefNumOffset) { FSRead(fd - kMacRefNumOffset, &cnt, buf); return cnt; } else return _consoleread(fd,buf,count); } int _open_r(struct _reent *reent, const char* name, int flags, int mode) { Str255 pname; #if TARGET_API_MAC_CARBON // Carbon has the new, sane version. c2pstrcpy(pname,name); #else // It is also available in various glue code libraries and // in some versions of InterfaceLib, but it's confusing. // Using the inplace variant, c2pstr, isn't much better than // doing things by hand: strncpy(&pname[1],name,255); pname[0] = strlen(name); #endif short ref; SInt8 permission; switch(flags & O_ACCMODE) { case O_RDONLY: permission = fsRdPerm; break; case O_WRONLY: permission = fsWrPerm; break; case O_RDWR: permission = fsRdWrPerm; break; } if(flags & O_CREAT) { HCreate(0,0,pname,'????','TEXT'); } OSErr err = HOpenDF(0,0,pname,fsRdWrPerm,&ref); if(err == paramErr) err = HOpen(0,0,pname,fsRdWrPerm,&ref); if(err) return -1; // TODO: errno if(flags & O_TRUNC) { SetEOF(ref, 0); } return ref + kMacRefNumOffset; } int _close_r(struct _reent *reent, int fd) { if(fd >= kMacRefNumOffset) { short refNum = fd - kMacRefNumOffset; short vRefNum; OSErr err = GetVRefNum(refNum, &vRefNum); FSClose(refNum); if (err == noErr) FlushVol(NULL, vRefNum); } return 0; } int _fstat_r(struct _reent *reent, int fd, struct stat *buf) { return -1; } extern int _stat_r(struct _reent * reent, const char *fn, struct stat *buf) { return -1; } off_t _lseek_r(struct _reent *reent, int fd, off_t offset, int whence) { if(fd >= kMacRefNumOffset) { short posMode; switch(whence) { case SEEK_SET: posMode = fsFromStart; break; case SEEK_CUR: posMode = fsFromMark; break; case SEEK_END: posMode = fsFromLEOF; break; } short ref = fd - kMacRefNumOffset; SetFPos(ref, posMode, offset); long finalPos; GetFPos(ref, &finalPos); return finalPos; } return (off_t) -1; } int _kill_r(struct _reent *reent, pid_t pid, int sig) { if(pid == 42) _exit(42); else return -1; } pid_t _getpid_r(struct _reent *reent) { return 42; } int _fork_r(struct _reent *reent) { return -1; } int _execve_r(struct _reent *reent, const char *fn, char *const * argv, char *const *envp) { return -1; } int _fcntl_r(struct _reent *reent, int fd, int cmd, int arg) { return -1; } int _isatty_r(struct _reent *reent, int fd) { return fd < kMacRefNumOffset; } int _link_r(struct _reent *reent, const char *from, const char *to) { reent->_errno = EPERM; return -1; } int _mkdir_r(struct _reent *reent, const char *fn, int mode) { return -1; } int _rename_r(struct _reent *reent, const char *from, const char *to) { return -1; } int _unlink_r(struct _reent *reent, const char *fn) { return -1; } _CLOCK_T_ _times_r(struct _reent *reent, struct tms *buf) { reent->_errno = EACCES; return -1; } int _wait_r(struct _reent *reent, int *wstatus) { reent->_errno = ECHILD; return -1; /* Always fails */ } int _gettimeofday_r(struct _reent *reent, struct timeval *tp, void *__tz) { /* Classic MacOS's GetDateTime function returns an integer. * TickCount() has a slightly higher resolution, but is independent of the real-time clock. */ unsigned long secs; GetDateTime(&secs); unsigned long ticks = TickCount(); static unsigned long savedTicks = 0, savedSecs = 0; if(!savedSecs) { savedTicks = ticks; savedSecs = secs; } else { unsigned long elapsedTicks = ticks - savedTicks; unsigned long elapsedSecs = secs - savedSecs; unsigned long expectedTicks = elapsedSecs * 60 + elapsedSecs * 3 / 20; if(expectedTicks > elapsedTicks) savedTicks = ticks; else savedTicks += expectedTicks; savedSecs = secs; } if(tp) { const int epochDifferenceInYears = 1970 - 1904; const int epochDifferenceInDays = 365 * epochDifferenceInYears + (epochDifferenceInYears + 3)/ 4; // round up for leap years tp->tv_sec = secs - 86400 * epochDifferenceInDays; tp->tv_usec = (ticks - savedTicks) * 20000000 / 2003; } return 0; }