diff --git a/changelog.md b/changelog.md index 4a490dfdde1e..773612902492 100644 --- a/changelog.md +++ b/changelog.md @@ -173,4 +173,7 @@ - ``experimental`` is now a pragma / command line switch that can enable specific language extensions, it is not an all-or-nothing switch anymore. +- Nintendo Switch was added as a new platform target. See [the compiler user guide](https://nim-lang.org/docs/nimc.html) + for more info. + ### Bugfixes diff --git a/compiler/extccomp.nim b/compiler/extccomp.nim index 615b8c1e1c75..1aa659fff022 100644 --- a/compiler/extccomp.nim +++ b/compiler/extccomp.nim @@ -83,6 +83,31 @@ compiler gcc: props: {hasSwitchRange, hasComputedGoto, hasCpp, hasGcGuard, hasGnuAsm, hasAttribute}) +# GNU C and C++ Compiler +compiler nintendoSwitchGCC: + result = ( + name: "switch_gcc", + objExt: "o", + optSpeed: " -O3 -ffast-math ", + optSize: " -Os -ffast-math ", + compilerExe: "aarch64-none-elf-gcc", + cppCompiler: "aarch64-none-elf-g++", + compileTmpl: "-MMD -MP -MF $dfile -c $options $include -o $objfile $file", + buildGui: " -mwindows", + buildDll: " -shared", + buildLib: "aarch64-none-elf-gcc-ar rcs $libfile $objfiles", + linkerExe: "aarch64-none-elf-gcc", + linkTmpl: "$buildgui $builddll -Wl,-Map,$mapfile -o $exefile $objfiles $options", + includeCmd: " -I", + linkDirCmd: " -L", + linkLibCmd: " -l$1", + debug: "", + pic: "-fPIE", + asmStmtFrmt: "asm($1);$n", + structStmtFmt: "$1 $3 $2 ", # struct|union [packed] $name + props: {hasSwitchRange, hasComputedGoto, hasCpp, hasGcGuard, hasGnuAsm, + hasAttribute}) + # LLVM Frontend for GCC/G++ compiler llvmGcc: result = gcc() # Uses settings from GCC @@ -316,6 +341,7 @@ compiler ucc: const CC*: array[succ(low(TSystemCC))..high(TSystemCC), TInfoCC] = [ gcc(), + nintendoSwitchGCC(), llvmGcc(), clang(), lcc(), @@ -556,14 +582,20 @@ proc getCompileCFileCmd*(conf: ConfigRef; cfile: Cfile): string = else: cfile.obj + # D files are required by nintendo switch libs for + # compilation. They are basically a list of all includes. + let dfile = objfile.changeFileExt(".d").quoteShell() + objfile = quoteShell(objfile) cf = quoteShell(cf) result = quoteShell(compilePattern % [ + "dfile", dfile, "file", cf, "objfile", objfile, "options", options, "include", includeCmd, "nim", getPrefixDir(conf), "nim", getPrefixDir(conf), "lib", conf.libpath]) add(result, ' ') addf(result, CC[c].compileTmpl, [ + "dfile", dfile, "file", cf, "objfile", objfile, "options", options, "include", includeCmd, "nim", quoteShell(getPrefixDir(conf)), @@ -659,16 +691,23 @@ proc getLinkCmd(conf: ConfigRef; projectfile, objfiles: string): string = if optCDebug in conf.globalOptions: writeDebugInfo(exefile.changeFileExt("ndb")) exefile = quoteShell(exefile) + + # Map files are required by Nintendo Switch compilation. They are a list + # of all function calls in the library and where they come from. + let mapfile = quoteShell(getNimcacheDir(conf) / splitFile(projectFile).name & ".map") + let linkOptions = getLinkOptions(conf) & " " & getConfigVar(conf, conf.cCompiler, ".options.linker") var linkTmpl = getConfigVar(conf, conf.cCompiler, ".linkTmpl") if linkTmpl.len == 0: linkTmpl = CC[conf.cCompiler].linkTmpl result = quoteShell(result % ["builddll", builddll, + "mapfile", mapfile, "buildgui", buildgui, "options", linkOptions, "objfiles", objfiles, "exefile", exefile, "nim", getPrefixDir(conf), "lib", conf.libpath]) result.add ' ' addf(result, linkTmpl, ["builddll", builddll, + "mapfile", mapfile, "buildgui", buildgui, "options", linkOptions, "objfiles", objfiles, "exefile", exefile, "nim", quoteShell(getPrefixDir(conf)), diff --git a/compiler/installer.ini b/compiler/installer.ini index 2847e4e62de6..79eb7178aa5b 100644 --- a/compiler/installer.ini +++ b/compiler/installer.ini @@ -15,6 +15,7 @@ Platforms: """ dragonfly: i386;amd64 haiku: i386;amd64 android: i386;arm;arm64 + nintendoswitch: arm64 """ Authors: "Andreas Rumpf" diff --git a/compiler/options.nim b/compiler/options.nim index 1d6ddb09f7d2..2aa515e35b5d 100644 --- a/compiler/options.nim +++ b/compiler/options.nim @@ -124,7 +124,7 @@ type disabledSf, writeOnlySf, readOnlySf, v2Sf TSystemCC* = enum - ccNone, ccGcc, ccLLVM_Gcc, ccCLang, ccLcc, ccBcc, ccDmc, ccWcc, ccVcc, + ccNone, ccGcc, ccNintendoSwitch, ccLLVM_Gcc, ccCLang, ccLcc, ccBcc, ccDmc, ccWcc, ccVcc, ccTcc, ccPcc, ccUcc, ccIcl, ccIcc CfileFlag* {.pure.} = enum @@ -345,7 +345,7 @@ proc isDefined*(conf: ConfigRef; symbol: string): bool = osQnx, osAtari, osAix, osHaiku, osVxWorks, osSolaris, osNetbsd, osFreebsd, osOpenbsd, osDragonfly, osMacosx, - osAndroid} + osAndroid, osNintendoSwitch} of "linux": result = conf.target.targetOS in {osLinux, osAndroid} of "bsd": @@ -356,6 +356,8 @@ proc isDefined*(conf: ConfigRef; symbol: string): bool = of "mswindows", "win32": result = conf.target.targetOS == osWindows of "macintosh": result = conf.target.targetOS in {osMacos, osMacosx} of "sunos": result = conf.target.targetOS == osSolaris + of "nintendoswitch": + result = conf.target.targetOS == osNintendoSwitch of "littleendian": result = CPU[conf.target.targetCPU].endian == platform.littleEndian of "bigendian": result = CPU[conf.target.targetCPU].endian == platform.bigEndian of "cpu8": result = CPU[conf.target.targetCPU].bit == 8 diff --git a/compiler/platform.nim b/compiler/platform.nim index 0db16f26c867..7eb8978168c8 100644 --- a/compiler/platform.nim +++ b/compiler/platform.nim @@ -22,7 +22,7 @@ type osNone, osDos, osWindows, osOs2, osLinux, osMorphos, osSkyos, osSolaris, osIrix, osNetbsd, osFreebsd, osOpenbsd, osDragonfly, osAix, osPalmos, osQnx, osAmiga, osAtari, osNetware, osMacos, osMacosx, osHaiku, osAndroid, osVxworks - osGenode, osJS, osNimVM, osStandalone + osGenode, osJS, osNimVM, osStandalone, osNintendoSwitch type TInfoOSProp* = enum @@ -168,7 +168,12 @@ const (name: "Standalone", parDir: "..", dllFrmt: "lib$1.so", altDirSep: "/", objExt: ".o", newLine: "\x0A", pathSep: ":", dirSep: "/", scriptExt: ".sh", curDir: ".", exeExt: "", extSep: ".", - props: {})] + props: {}), + (name: "NintendoSwitch", parDir: "..", dllFrmt: "lib$1.so", altDirSep: "/", + objExt: ".o", newLine: "\x0A", pathSep: ":", dirSep: "/", + scriptExt: ".sh", curDir: ".", exeExt: ".elf", extSep: ".", + props: {ospNeedsPIC, ospPosix}), + ] type TSystemCPU* = enum # Also add CPU for in initialization section and diff --git a/config/nim.cfg b/config/nim.cfg index e11826587e34..626f4494a1e5 100644 --- a/config/nim.cfg +++ b/config/nim.cfg @@ -109,6 +109,14 @@ path="$lib/pure" @end @end +@if nintendoswitch: + cc = "switch_gcc" + switch_gcc.options.linker = "-g -march=armv8-a -mtune=cortex-a57 -mtp=soft -fPIE $SWITCH_LIBS" + switch_gcc.cpp.options.linker = "-g -march=armv8-a -mtune=cortex-a57 -mtp=soft -fPIE $SWITCH_LIBS" + switch_gcc.options.always = "-g -Wall -O2 -ffunction-sections -march=armv8-a -mtune=cortex-a57 -mtp=soft -fPIE $SWITCH_INCLUDES -D__SWITCH__" + switch_gcc.cpp.options.always = "-g -Wall -O2 -ffunction-sections -march=armv8-a -mtune=cortex-a57 -mtp=soft -fPIE $SWITCH_INCLUDES -D__SWITCH__ -fno-rtti -fno-exceptions -std=gnu++11" +@end + # Configuration for the Intel C/C++ compiler: @if windows: icl.options.speed = "/Ox /arch:SSE2" diff --git a/doc/nimc.rst b/doc/nimc.rst index 29dbdea42900..a3adcc143d44 100644 --- a/doc/nimc.rst +++ b/doc/nimc.rst @@ -228,6 +228,52 @@ configuration file should contain something like:: arm.linux.gcc.exe = "arm-linux-gcc" arm.linux.gcc.linkerexe = "arm-linux-gcc" +Cross compilation for Nintendo Switch +===================================== + +Simply add --os:nintendoswitch +to your usual ``nim c`` or ``nim cpp`` command and set the ``SWITCH_LIBS`` +and ``SWITCH_INCLUDES`` environment variables to something like: + +.. code-block:: console + export SWITCH_INCLUDES="-I$DEVKITPRO/libnx/include" + export SWITCH_LIBS="-specs=$DEVKITPRO/libnx/switch.specs -L$DEVKITPRO/libnx/lib -lnx" + +or setup a nim.cfg file like so: + +.. code-block:: Nim + #nim.cfg + --passC="-I$DEVKITPRO/libnx/include" + --passL="-specs=$DEVKITPRO/libnx/switch.specs -L$DEVKITPRO/libnx/lib -lnx" + +The DevkitPro setup must be the same as the default with their new installer +`here for Mac/Linux `_ or +`here for Windows `_. + +For example, with the above mentioned config:: + + nim c --os:nintendoswitch switchhomebrew.nim + +This will generate a file called ``switchhomebrew.elf`` which can then be turned into +an nro file with the ``elf2nro`` tool in the DevkitPro release. Examples can be found at +`the nim-libnx github repo `_ or you can use +`the switch builder tool `_. + +Environment variables are: + - ``SWITCH_LIBS`` for any extra libraries required by your application (``-lLIBNAME`` or ``-LLIBPATH``) + - ``SWITCH_INCLUDES`` for any extra include files (``-IINCLUDE_PATH``) + +There are a few things that don't work because the DevkitPro libraries don't support them. +They are: + +1. Waiting for a subprocess to finish. A subprocess can be started, but right + now it can't be waited on, which sort of makes subprocesses a bit hard to use +2. Dynamic calls. DevkitPro libraries have no dlopen/dlclose functions. +3. Command line parameters. It doesn't make sense to have these for a console + anyways, so no big deal here. +4. mqueue. Sadly there are no mqueue headers. +5. ucontext. No headers for these either. No coroutines for now :( +6. nl_types. No headers for this. DLL generation ============== diff --git a/lib/nintendoswitch/switch_memory.nim b/lib/nintendoswitch/switch_memory.nim new file mode 100644 index 000000000000..09b34c5d01d3 --- /dev/null +++ b/lib/nintendoswitch/switch_memory.nim @@ -0,0 +1,21 @@ +const virtMemHeader = "" +const svcHeader = "" +const mallocHeader = "" + +proc memalign*(bytes: csize, size: csize): pointer {.importc: "memalign", + header: mallocHeader.} + +proc free*(address: pointer) {.importc: "free", + header: mallocHeader.} + +proc svcMapMemory*(dst_addr: pointer; src_addr: pointer; size: uint64): uint32 {. + importc: "svcMapMemory", header: svcHeader.} + +proc svcUnmapMemory*(dst_addr: pointer; src_addr: pointer; size: uint64): uint32 {. + importc: "svcUnmapMemory", header: svcHeader.} + +proc virtmemReserveMap*(size: csize): pointer {.importc: "virtmemReserveMap", + header: virtMemHeader.} + +proc virtmemFreeMap*(address: pointer; size: csize) {.importc: "virtmemFreeMap", + header: virtMemHeader.} diff --git a/lib/posix/posix.nim b/lib/posix/posix.nim index db5f575afb85..97b4124ec417 100644 --- a/lib/posix/posix.nim +++ b/lib/posix/posix.nim @@ -94,6 +94,8 @@ const StatHasNanoseconds* = defined(linux) or defined(freebsd) or when defined(linux) and defined(amd64): include posix_linux_amd64 +elif defined(nintendoswitch): + include posix_nintendoswitch else: include posix_other @@ -185,7 +187,7 @@ proc fnmatch*(a1, a2: cstring, a3: cint): cint {.importc, header: "". proc ftw*(a1: cstring, a2: proc (x1: cstring, x2: ptr Stat, x3: cint): cint {.noconv.}, a3: cint): cint {.importc, header: "".} -when not (defined(linux) and defined(amd64)): +when not (defined(linux) and defined(amd64)) and not defined(nintendoswitch): proc nftw*(a1: cstring, a2: proc (x1: cstring, x2: ptr Stat, x3: cint, x4: ptr FTW): cint {.noconv.}, @@ -226,25 +228,26 @@ proc setlocale*(a1: cint, a2: cstring): cstring {. proc strfmon*(a1: cstring, a2: int, a3: cstring): int {.varargs, importc, header: "".} -proc mq_close*(a1: Mqd): cint {.importc, header: "".} -proc mq_getattr*(a1: Mqd, a2: ptr MqAttr): cint {. - importc, header: "".} -proc mq_notify*(a1: Mqd, a2: ptr SigEvent): cint {. - importc, header: "".} -proc mq_open*(a1: cstring, a2: cint): Mqd {. - varargs, importc, header: "".} -proc mq_receive*(a1: Mqd, a2: cstring, a3: int, a4: var int): int {. - importc, header: "".} -proc mq_send*(a1: Mqd, a2: cstring, a3: int, a4: int): cint {. - importc, header: "".} -proc mq_setattr*(a1: Mqd, a2, a3: ptr MqAttr): cint {. - importc, header: "".} - -proc mq_timedreceive*(a1: Mqd, a2: cstring, a3: int, a4: int, - a5: ptr Timespec): int {.importc, header: "".} -proc mq_timedsend*(a1: Mqd, a2: cstring, a3: int, a4: int, - a5: ptr Timespec): cint {.importc, header: "".} -proc mq_unlink*(a1: cstring): cint {.importc, header: "".} +when not defined(nintendoswitch): + proc mq_close*(a1: Mqd): cint {.importc, header: "".} + proc mq_getattr*(a1: Mqd, a2: ptr MqAttr): cint {. + importc, header: "".} + proc mq_notify*(a1: Mqd, a2: ptr SigEvent): cint {. + importc, header: "".} + proc mq_open*(a1: cstring, a2: cint): Mqd {. + varargs, importc, header: "".} + proc mq_receive*(a1: Mqd, a2: cstring, a3: int, a4: var int): int {. + importc, header: "".} + proc mq_send*(a1: Mqd, a2: cstring, a3: int, a4: int): cint {. + importc, header: "".} + proc mq_setattr*(a1: Mqd, a2, a3: ptr MqAttr): cint {. + importc, header: "".} + + proc mq_timedreceive*(a1: Mqd, a2: cstring, a3: int, a4: int, + a5: ptr Timespec): int {.importc, header: "".} + proc mq_timedsend*(a1: Mqd, a2: cstring, a3: int, a4: int, + a5: ptr Timespec): cint {.importc, header: "".} + proc mq_unlink*(a1: cstring): cint {.importc, header: "".} proc getpwnam*(a1: cstring): ptr Passwd {.importc, header: "".} @@ -603,7 +606,7 @@ proc posix_madvise*(a1: pointer, a2: int, a3: cint): cint {. importc, header: "".} proc posix_mem_offset*(a1: pointer, a2: int, a3: var Off, a4: var int, a5: var cint): cint {.importc, header: "".} -when not (defined(linux) and defined(amd64)): +when not (defined(linux) and defined(amd64)) and not defined(nintendoswitch): proc posix_typed_mem_get_info*(a1: cint, a2: var Posix_typed_mem_info): cint {.importc, header: "".} proc posix_typed_mem_open*(a1: cstring, a2, a3: cint): cint {. @@ -713,12 +716,12 @@ proc sigwait*(a1: var Sigset, a2: var cint): cint {. proc sigwaitinfo*(a1: var Sigset, a2: var SigInfo): cint {. importc, header: "".} - -proc catclose*(a1: Nl_catd): cint {.importc, header: "".} -proc catgets*(a1: Nl_catd, a2, a3: cint, a4: cstring): cstring {. - importc, header: "".} -proc catopen*(a1: cstring, a2: cint): Nl_catd {. - importc, header: "".} +when not defined(nintendoswitch): + proc catclose*(a1: Nl_catd): cint {.importc, header: "".} + proc catgets*(a1: Nl_catd, a2, a3: cint, a4: cstring): cstring {. + importc, header: "".} + proc catopen*(a1: cstring, a2: cint): Nl_catd {. + importc, header: "".} proc sched_get_priority_max*(a1: cint): cint {.importc, header: "".} proc sched_get_priority_min*(a1: cint): cint {.importc, header: "".} @@ -800,11 +803,12 @@ when hasSpawnH: a4: var Tposix_spawnattr, a5, a6: cstringArray): cint {.importc, header: "".} -proc getcontext*(a1: var Ucontext): cint {.importc, header: "".} -proc makecontext*(a1: var Ucontext, a4: proc (){.noconv.}, a3: cint) {. - varargs, importc, header: "".} -proc setcontext*(a1: var Ucontext): cint {.importc, header: "".} -proc swapcontext*(a1, a2: var Ucontext): cint {.importc, header: "".} +when not defined(nintendoswitch): + proc getcontext*(a1: var Ucontext): cint {.importc, header: "".} + proc makecontext*(a1: var Ucontext, a4: proc (){.noconv.}, a3: cint) {. + varargs, importc, header: "".} + proc setcontext*(a1: var Ucontext): cint {.importc, header: "".} + proc swapcontext*(a1, a2: var Ucontext): cint {.importc, header: "".} proc readv*(a1: cint, a2: ptr IOVec, a3: cint): int {. importc, header: "".} diff --git a/lib/posix/posix_nintendoswitch.nim b/lib/posix/posix_nintendoswitch.nim new file mode 100644 index 000000000000..892ea33701d1 --- /dev/null +++ b/lib/posix/posix_nintendoswitch.nim @@ -0,0 +1,506 @@ +# +# +# Nim's Runtime Library +# (c) Copyright 2018 Joey Yakimowich-Payne +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +# To be included from posix.nim! + +const + hasSpawnH = true + hasAioH = false + +type + DIR* {.importc: "DIR", header: "", + incompleteStruct.} = object + +const SIG_HOLD* = cast[SigHandler](2) + +type + SocketHandle* = distinct cint # The type used to represent socket descriptors + +type + Time* {.importc: "time_t", header: "".} = distinct clong + + Timespec* {.importc: "struct timespec", + header: "", final, pure.} = object ## struct timespec + tv_sec*: Time ## Seconds. + tv_nsec*: clong ## Nanoseconds. + + Dirent* {.importc: "struct dirent", + header: "", final, pure.} = object ## dirent_t struct + d_ino*: Ino + d_type*: int8 # cuchar really! + d_name*: array[256, cchar] + + Tflock* {.importc: "struct flock", final, pure, + header: "".} = object ## flock type + l_type*: cshort ## Type of lock; F_RDLCK, F_WRLCK, F_UNLCK. + l_whence*: cshort ## Flag for starting offset. + l_start*: Off ## Relative offset in bytes. + l_len*: Off ## Size; if 0 then until EOF. + l_pid*: Pid ## Process ID of the process holding the lock; + ## returned with F_GETLK. + + # no struct FTW on linux + + Glob* {.importc: "glob_t", header: "", + final, pure.} = object ## glob_t + gl_pathc*: cint ## Count of paths matched by pattern. + gl_matchc*: cint ## Count of paths matching pattern + gl_offs*: cint ## Slots to reserve at the beginning of gl_pathv. + gl_flags*: cint + gl_pathv*: cstringArray ## Pointer to a list of matched pathnames. + gl_errfunc*: pointer + gl_closedir*: pointer + gl_readdir*: pointer + gl_opendir*: pointer + gl_lstat*: pointer + gl_stat*: pointer + + Group* {.importc: "struct group", header: "", + final, pure.} = object ## struct group + gr_name*: cstring ## The name of the group. + gr_passwd*: cstring + gr_gid*: Gid ## Numerical group ID. + gr_mem*: cstringArray ## Pointer to a null-terminated array of character + ## pointers to member names. + + Iconv* {.importc: "iconv_t", header: "".} = pointer + ## Identifies the conversion from one codeset to another. + + Lconv* {.importc: "struct lconv", header: "", final, + pure.} = object + decimal_point*: cstring + thousands_sep*: cstring + grouping*: cstring + int_curr_symbol*: cstring + currency_symbol*: cstring + mon_decimal_point*: cstring + mon_thousands_sep*: cstring + mon_grouping*: cstring + positive_sign*: cstring + negative_sign*: cstring + int_frac_digits*: char + frac_digits*: char + p_cs_precedes*: char + p_sep_by_space*: char + n_cs_precedes*: char + n_sep_by_space*: char + p_sign_posn*: char + n_sign_posn*: char + int_n_cs_precedes*: char + int_n_sep_by_space*: char + int_n_sign_posn*: char + int_p_cs_precedes*: char + int_p_sep_by_space*: char + int_p_sign_posn*: char + + Passwd* {.importc: "struct passwd", header: "", + final, pure.} = object ## struct passwd + pw_name*: cstring ## User's login name. + pw_passwd*: cstring + pw_uid*: Uid ## Numerical user ID. + pw_gid*: Gid ## Numerical group ID. + pw_comment*: cstring + pw_gecos*: cstring + pw_dir*: cstring ## Initial working directory. + pw_shell*: cstring ## Program to use as shell. + + Blkcnt* {.importc: "blkcnt_t", header: "".} = clong + ## used for file block counts + Blksize* {.importc: "blksize_t", header: "".} = clong + ## used for block sizes + Clock* {.importc: "clock_t", header: "".} = clong + ClockId* {.importc: "clockid_t", header: "".} = cint + Dev* {.importc: "dev_t", header: "".} = culong + Fsblkcnt* {.importc: "fsblkcnt_t", header: "".} = culong + Fsfilcnt* {.importc: "fsfilcnt_t", header: "".} = culong + Gid* {.importc: "gid_t", header: "".} = cuint + Id* {.importc: "id_t", header: "".} = cuint + Ino* {.importc: "ino_t", header: "".} = culong + Key* {.importc: "key_t", header: "".} = cint + Mode* {.importc: "mode_t", header: "".} = cint # cuint really! + Nlink* {.importc: "nlink_t", header: "".} = culong + Off* {.importc: "off_t", header: "".} = clong + Pid* {.importc: "pid_t", header: "".} = cint + Pthread_attr* {.importc: "pthread_attr_t", header: "", + pure, final.} = object + abi: array[56 div sizeof(clong), clong] + + Pthread_barrier* {.importc: "pthread_barrier_t", + header: "", pure, final.} = object + abi: array[32 div sizeof(clong), clong] + Pthread_barrierattr* {.importc: "pthread_barrierattr_t", + header: "", pure, final.} = object + abi: array[4 div sizeof(cint), cint] + + Pthread_cond* {.importc: "pthread_cond_t", header: "", + pure, final.} = object + abi: array[48 div sizeof(clonglong), clonglong] + Pthread_condattr* {.importc: "pthread_condattr_t", + header: "", pure, final.} = object + abi: array[4 div sizeof(cint), cint] + Pthread_key* {.importc: "pthread_key_t", header: "".} = cuint + Pthread_mutex* {.importc: "pthread_mutex_t", header: "", + pure, final.} = object + abi: array[48 div sizeof(clong), clong] + Pthread_mutexattr* {.importc: "pthread_mutexattr_t", + header: "", pure, final.} = object + abi: array[4 div sizeof(cint), cint] + Pthread_once* {.importc: "pthread_once_t", header: "".} = cint + Pthread_rwlock* {.importc: "pthread_rwlock_t", + header: "", pure, final.} = object + abi: array[56 div sizeof(clong), clong] + Pthread_rwlockattr* {.importc: "pthread_rwlockattr_t", + header: "".} = object + abi: array[8 div sizeof(clong), clong] + Pthread_spinlock* {.importc: "pthread_spinlock_t", + header: "".} = cint + Pthread* {.importc: "pthread_t", header: "".} = culong + Suseconds* {.importc: "suseconds_t", header: "".} = clong + #Ttime* {.importc: "time_t", header: "".} = int + Timer* {.importc: "timer_t", header: "".} = pointer + Uid* {.importc: "uid_t", header: "".} = cuint + Useconds* {.importc: "useconds_t", header: "".} = cuint + + Utsname* {.importc: "struct utsname", + header: "", + final, pure.} = object ## struct utsname + sysname*, ## Name of this implementation of the operating system. + nodename*, ## Name of this node within the communications + ## network to which this node is attached, if any. + release*, ## Current release level of this implementation. + version*, ## Current version level of this release. + machine*, ## Name of the hardware type on which the + ## system is running. + domainname*: array[65, char] + + Sem* {.importc: "sem_t", header: "", final, pure.} = object + abi: array[32 div sizeof(clong), clong] + + Stat* {.importc: "struct stat", + header: "", final, pure.} = object ## struct stat + st_dev*: Dev ## Device ID of device containing file. + st_ino*: Ino ## File serial number. + st_mode*: Mode ## Mode of file (see below). + st_nlink*: Nlink ## Number of hard links to the file. + st_uid*: Uid ## User ID of file. + st_gid*: Gid ## Group ID of file. + st_rdev*: Dev ## Device ID (if file is character or block special). + st_size*: Off ## For regular files, the file size in bytes. + ## For symbolic links, the length in bytes of the + ## pathname contained in the symbolic link. + ## For a shared memory object, the length in bytes. + ## For a typed memory object, the length in bytes. + ## For other file types, the use of this field is + ## unspecified. + when StatHasNanoseconds: + st_atim*: Timespec ## Time of last access. + pad1: clong + st_mtim*: Timespec ## Time of last data modification. + pad2: clong + st_ctim*: Timespec ## Time of last status change. + pad3: clong + else: + st_atime*: Time ## Time of last access. + pad1: clong + st_mtime*: Time ## Time of last data modification. + pad2: clong + st_ctime*: Time ## Time of last status change. + pad3: clong + st_blksize*: Blksize ## A file system-specific preferred I/O block size + ## for this object. In some file system types, this + ## may vary from file to file. + st_blocks*: Blkcnt ## Number of blocks allocated for this object. + reserved: array[2, clong] + + + + Statvfs* {.importc: "struct statvfs", header: "", + final, pure.} = object ## struct statvfs + f_bsize*: culong ## File system block size. + f_frsize*: culong ## Fundamental file system block size. + f_blocks*: Fsblkcnt ## Total number of blocks on file system + ## in units of f_frsize. + f_bfree*: Fsblkcnt ## Total number of free blocks. + f_bavail*: Fsblkcnt ## Number of free blocks available to + ## non-privileged process. + f_files*: Fsfilcnt ## Total number of file serial numbers. + f_ffree*: Fsfilcnt ## Total number of free file serial numbers. + f_favail*: Fsfilcnt ## Number of file serial numbers available to + ## non-privileged process. + f_fsid*: culong ## File system ID. + f_flag*: culong ## Bit mask of f_flag values. + f_namemax*: culong ## Maximum filename length. + + # No Posix_typed_mem_info + + Tm* {.importc: "struct tm", header: "", + final, pure.} = object ## struct tm + tm_sec*: cint ## Seconds [0,60]. + tm_min*: cint ## Minutes [0,59]. + tm_hour*: cint ## Hour [0,23]. + tm_mday*: cint ## Day of month [1,31]. + tm_mon*: cint ## Month of year [0,11]. + tm_year*: cint ## Years since 1900. + tm_wday*: cint ## Day of week [0,6] (Sunday =0). + tm_yday*: cint ## Day of year [0,365]. + tm_isdst*: cint ## Daylight Savings flag. + + Itimerspec* {.importc: "struct itimerspec", header: "", + final, pure.} = object ## struct itimerspec + it_interval*: Timespec ## Timer period. + it_value*: Timespec ## Timer expiration. + + Sig_atomic* {.importc: "sig_atomic_t", header: "".} = cint + ## Possibly volatile-qualified integer type of an object that can be + ## accessed as an atomic entity, even in the presence of asynchronous + ## interrupts. + Sigset* {.importc: "sigset_t", header: "", final.} = culong + + SigEvent* {.importc: "struct sigevent", + header: "", final, pure.} = object ## struct sigevent + sigev_notify*: cint ## Notification type. + sigev_signo*: cint ## Signal number. + sigev_value*: SigVal ## Signal value. + + SigVal* {.importc: "union sigval", + header: "", final, pure.} = object ## struct sigval + sival_int*: cint ## integer signal value + sival_ptr*: pointer ## pointer signal value; + + Sigaction* {.importc: "struct sigaction", + header: "", final, pure.} = object ## struct sigaction + sa_handler*: proc (x: cint) {.noconv.} ## Pointer to a signal-catching + ## function or one of the macros + ## SIG_IGN or SIG_DFL. + sa_mask*: Sigset ## Set of signals to be blocked during execution of + ## the signal handling function. + sa_flags*: cint ## Special flags. + + Stack* {.importc: "stack_t", + header: "", final, pure.} = object ## stack_t + ss_sp*: pointer ## Stack base or pointer. + ss_flags*: cint ## Flags. + ss_size*: csize ## Stack size. + + SigInfo* {.importc: "siginfo_t", + header: "", final, pure.} = object ## siginfo_t + si_signo*: cint ## Signal number. + si_code*: cint ## Signal code. + si_value*: SigVal ## Signal value. + + Nl_item* {.importc: "nl_item", header: "".} = cint + + Sched_param* {.importc: "struct sched_param", + header: "", + final, pure.} = object ## struct sched_param + sched_priority*: cint + + Timeval* {.importc: "struct timeval", header: "", + final, pure.} = object ## struct timeval + tv_sec*: Time ## Seconds. + tv_usec*: Suseconds ## Microseconds. + TFdSet* {.importc: "fd_set", header: "", + final, pure.} = object + abi: array[((64+(sizeof(clong) * 8)-1) div (sizeof(clong) * 8)), clong] + +proc si_pid*(info: SigInfo): Pid = + ## This might not be correct behavior. si_pid doesn't exist in Switch's + ## devkitpro headers + raise newException(OSError, "Nintendo switch cannot get si_pid!") + +type + Taiocb* {.importc: "struct aiocb", header: "", + final, pure.} = object ## struct aiocb + aio_fildes*: cint ## File descriptor. + aio_lio_opcode*: cint ## Operation to be performed. + aio_reqprio*: cint ## Request priority offset. + aio_buf*: pointer ## Location of buffer. + aio_nbytes*: csize ## Length of transfer. + aio_sigevent*: SigEvent ## Signal number and value. + next_prio: pointer + abs_prio: cint + policy: cint + error_Code: cint + return_value: clong + aio_offset*: Off ## File offset. + reserved: array[32, uint8] + +type + Tposix_spawnattr* {.importc: "posix_spawnattr_t", + header: "", final, pure.} = object + Tposix_spawn_file_actions* {.importc: "posix_spawn_file_actions_t", + header: "", final, pure.} = object + +# from sys/un.h +const Sockaddr_un_path_length* = 108 + +type + Socklen* {.importc: "socklen_t", header: "".} = cuint + # cushort really + TSa_Family* {.importc: "sa_family_t", header: "".} = cshort + + SockAddr* {.importc: "struct sockaddr", header: "", + pure, final.} = object ## struct sockaddr + sa_len: cuchar + sa_family*: TSa_Family ## Address family. + sa_data*: array[14, char] ## Socket address (variable-length data). + + Sockaddr_storage* {.importc: "struct sockaddr_storage", + header: "", + pure, final.} = object ## struct sockaddr_storage + ss_len: cuchar + ss_family*: TSa_Family ## Address family. + ss_padding1: array[64 - sizeof(cuchar) - sizeof(cshort), char] + ss_align: clonglong + ss_padding2: array[ + 128 - sizeof(cuchar) - sizeof(cshort) - + (64 - sizeof(cuchar) - sizeof(cshort)) - 64, char] + + Tif_nameindex* {.importc: "struct if_nameindex", final, + pure, header: "".} = object ## struct if_nameindex + if_index*: cuint ## Numeric index of the interface. + if_name*: cstring ## Null-terminated name of the interface. + + + IOVec* {.importc: "struct iovec", pure, final, + header: "".} = object ## struct iovec + iov_base*: pointer ## Base address of a memory region for input or output. + iov_len*: csize ## The size of the memory pointed to by iov_base. + + Tmsghdr* {.importc: "struct msghdr", pure, final, + header: "".} = object ## struct msghdr + msg_name*: pointer ## Optional address. + msg_namelen*: Socklen ## Size of address. + msg_iov*: ptr IOVec ## Scatter/gather array. + msg_iovlen*: csize ## Members in msg_iov. + msg_control*: pointer ## Ancillary data; see below. + msg_controllen*: csize ## Ancillary data buffer len. + msg_flags*: cint ## Flags on received message. + + + Tcmsghdr* {.importc: "struct cmsghdr", pure, final, + header: "".} = object ## struct cmsghdr + cmsg_len*: csize ## Data byte count, including the cmsghdr. + cmsg_level*: cint ## Originating protocol. + cmsg_type*: cint ## Protocol-specific type. + + TLinger* {.importc: "struct linger", pure, final, + header: "".} = object ## struct linger + l_onoff*: cint ## Indicates whether linger option is enabled. + l_linger*: cint ## Linger time, in seconds. + # data follows... + + InPort* = uint16 + InAddrScalar* = uint32 + + InAddrT* {.importc: "in_addr_t", pure, final, + header: "".} = uint32 + + InAddr* {.importc: "struct in_addr", pure, final, + header: "".} = object ## struct in_addr + s_addr*: InAddrScalar + + Sockaddr_in* {.importc: "struct sockaddr_in", pure, final, + header: "".} = object ## struct sockaddr_in + sin_len*: cushort + sin_family*: TSa_Family ## AF_INET. + sin_port*: InPort ## Port number. + sin_addr*: InAddr ## IP address. + sin_zero: array[8, uint8] + + In6Addr* {.importc: "struct in6_addr", pure, final, + header: "".} = object ## struct in6_addr + s6_addr*: array[0..15, char] + + Sockaddr_in6* {.importc: "struct sockaddr_in6", pure, final, + header: "".} = object ## struct sockaddr_in6 + sin6_family*: TSa_Family ## AF_INET6. + sin6_port*: InPort ## Port number. + sin6_flowinfo*: uint32 ## IPv6 traffic class and flow information. + sin6_addr*: In6Addr ## IPv6 address. + sin6_scope_id*: uint32 ## Set of interfaces for a scope. + + Hostent* {.importc: "struct hostent", pure, final, + header: "".} = object ## struct hostent + h_name*: cstring ## Official name of the host. + h_aliases*: cstringArray ## A pointer to an array of pointers to + ## alternative host names, terminated by a + ## null pointer. + h_addrtype*: cint ## Address type. + h_length*: cint ## The length, in bytes, of the address. + h_addr_list*: cstringArray ## A pointer to an array of pointers to network + ## addresses (in network byte order) for the + ## host, terminated by a null pointer. + + Tnetent* {.importc: "struct netent", pure, final, + header: "".} = object ## struct netent + n_name*: cstring ## Official, fully-qualified (including the + ## domain) name of the host. + n_aliases*: cstringArray ## A pointer to an array of pointers to + ## alternative network names, terminated by a + ## null pointer. + n_addrtype*: cint ## The address type of the network. + n_net*: uint32 ## The network number, in host byte order. + + Protoent* {.importc: "struct protoent", pure, final, + header: "".} = object ## struct protoent + p_name*: cstring ## Official name of the protocol. + p_aliases*: cstringArray ## A pointer to an array of pointers to + ## alternative protocol names, terminated by + ## a null pointer. + p_proto*: cint ## The protocol number. + + Servent* {.importc: "struct servent", pure, final, + header: "".} = object ## struct servent + s_name*: cstring ## Official name of the service. + s_aliases*: cstringArray ## A pointer to an array of pointers to + ## alternative service names, terminated by + ## a null pointer. + s_port*: cint ## The port number at which the service + ## resides, in network byte order. + s_proto*: cstring ## The name of the protocol to use when + ## contacting the service. + + AddrInfo* {.importc: "struct addrinfo", pure, final, + header: "".} = object ## struct addrinfo + ai_flags*: cint ## Input flags. + ai_family*: cint ## Address family of socket. + ai_socktype*: cint ## Socket type. + ai_protocol*: cint ## Protocol of socket. + ai_addrlen*: Socklen ## Length of socket address. + ai_canonname*: cstring ## Canonical name of service location. + ai_addr*: ptr SockAddr ## Socket address of socket. + ai_next*: ptr AddrInfo ## Pointer to next in list. + + TPollfd* {.importc: "struct pollfd", pure, final, + header: "".} = object ## struct pollfd + fd*: cint ## The following descriptor being polled. + events*: cshort ## The input event flags (see below). + revents*: cshort ## The output event flags (see below). + + Tnfds* {.importc: "nfds_t", header: "".} = culong + +var + errno* {.importc, header: "".}: cint ## error variable + h_errno* {.importc, header: "".}: cint + daylight* {.importc: "_daylight", header: "".}: cint + timezone* {.importc: "_timezone", header: "".}: clong + +# Regenerate using detect.nim! +include posix_nintendoswitch_consts + +const POSIX_SPAWN_USEVFORK* = cint(0x40) # needs _GNU_SOURCE! + +# +proc WEXITSTATUS*(s: cint): cint = (s shr 8) and 0xff +proc WIFEXITED*(s:cint) : bool = (s and 0xff) == 0 +proc WTERMSIG*(s:cint): cint = s and 0x7f +proc WSTOPSIG*(s:cint): cint = WEXITSTATUS(s) +proc WIFSIGNALED*(s:cint) : bool = ((s and 0x7f) > 0) and ((s and 0x7f) < 0x7f) +proc WIFSTOPPED*(s:cint) : bool = (s and 0xff) == 0x7f diff --git a/lib/posix/posix_nintendoswitch_consts.nim b/lib/posix/posix_nintendoswitch_consts.nim new file mode 100644 index 000000000000..33470d22bb70 --- /dev/null +++ b/lib/posix/posix_nintendoswitch_consts.nim @@ -0,0 +1,586 @@ +# Generated by detect.nim + + +# + +# + +# +const E2BIG* = cint(7) +const EACCES* = cint(13) +const EADDRINUSE* = cint(112) +const EADDRNOTAVAIL* = cint(125) +const EAFNOSUPPORT* = cint(106) +const EAGAIN* = cint(11) +const EALREADY* = cint(120) +const EBADF* = cint(9) +const EBADMSG* = cint(77) +const EBUSY* = cint(16) +const ECANCELED* = cint(140) +const ECHILD* = cint(10) +const ECONNABORTED* = cint(113) +const ECONNREFUSED* = cint(111) +const ECONNRESET* = cint(104) +const EDEADLK* = cint(45) +const EDESTADDRREQ* = cint(121) +const EDOM* = cint(33) +const EDQUOT* = cint(132) +const EEXIST* = cint(17) +const EFAULT* = cint(14) +const EFBIG* = cint(27) +const EHOSTUNREACH* = cint(118) +const EIDRM* = cint(36) +const EILSEQ* = cint(138) +const EINPROGRESS* = cint(119) +const EINTR* = cint(4) +const EINVAL* = cint(22) +const EIO* = cint(5) +const EISCONN* = cint(127) +const EISDIR* = cint(21) +const ELOOP* = cint(92) +const EMFILE* = cint(24) +const EMLINK* = cint(31) +const EMSGSIZE* = cint(122) +const EMULTIHOP* = cint(74) +const ENAMETOOLONG* = cint(91) +const ENETDOWN* = cint(115) +const ENETRESET* = cint(126) +const ENETUNREACH* = cint(114) +const ENFILE* = cint(23) +const ENOBUFS* = cint(105) +const ENODATA* = cint(61) +const ENODEV* = cint(19) +const ENOENT* = cint(2) +const ENOEXEC* = cint(8) +const ENOLCK* = cint(46) +const ENOLINK* = cint(67) +const ENOMEM* = cint(12) +const ENOMSG* = cint(35) +const ENOPROTOOPT* = cint(109) +const ENOSPC* = cint(28) +const ENOSR* = cint(63) +const ENOSTR* = cint(60) +const ENOSYS* = cint(88) +const ENOTCONN* = cint(128) +const ENOTDIR* = cint(20) +const ENOTEMPTY* = cint(90) +const ENOTSOCK* = cint(108) +const ENOTSUP* = cint(134) +const ENOTTY* = cint(25) +const ENXIO* = cint(6) +const EOPNOTSUPP* = cint(95) +const EOVERFLOW* = cint(139) +const EPERM* = cint(1) +const EPIPE* = cint(32) +const EPROTO* = cint(71) +const EPROTONOSUPPORT* = cint(123) +const EPROTOTYPE* = cint(107) +const ERANGE* = cint(34) +const EROFS* = cint(30) +const ESPIPE* = cint(29) +const ESRCH* = cint(3) +const ESTALE* = cint(133) +const ETIME* = cint(62) +const ETIMEDOUT* = cint(116) +const ETXTBSY* = cint(26) +const EWOULDBLOCK* = cint(11) +const EXDEV* = cint(18) + +# +const F_DUPFD* = cint(0) +const F_GETFD* = cint(1) +const F_SETFD* = cint(2) +const F_GETFL* = cint(3) +const F_SETFL* = cint(4) +const F_GETLK* = cint(7) +const F_SETLK* = cint(8) +const F_SETLKW* = cint(9) +const F_GETOWN* = cint(5) +const F_SETOWN* = cint(6) +const FD_CLOEXEC* = cint(1) +const F_RDLCK* = cint(1) +const F_UNLCK* = cint(3) +const F_WRLCK* = cint(2) +const O_CREAT* = cint(512) +const O_EXCL* = cint(2048) +const O_NOCTTY* = cint(32768) +const O_TRUNC* = cint(1024) +const O_APPEND* = cint(8) +const O_NONBLOCK* = cint(16384) +const O_SYNC* = cint(8192) +const O_ACCMODE* = cint(3) +const O_RDONLY* = cint(0) +const O_RDWR* = cint(2) +const O_WRONLY* = cint(1) + +# + +# + +# +const FNM_NOMATCH* = cint(1) +const FNM_PATHNAME* = cint(2) +const FNM_PERIOD* = cint(4) +const FNM_NOESCAPE* = cint(1) + +# + +# +const GLOB_APPEND* = cint(1) +const GLOB_DOOFFS* = cint(2) +const GLOB_ERR* = cint(4) +const GLOB_MARK* = cint(8) +const GLOB_NOCHECK* = cint(16) +const GLOB_NOSORT* = cint(32) +const GLOB_NOSPACE* = cint(-1) + +# +const CODESET* = cint(0) +const D_T_FMT* = cint(1) +const D_FMT* = cint(2) +const T_FMT* = cint(3) +const T_FMT_AMPM* = cint(4) +const AM_STR* = cint(5) +const PM_STR* = cint(6) +const DAY_1* = cint(7) +const DAY_2* = cint(8) +const DAY_3* = cint(9) +const DAY_4* = cint(10) +const DAY_5* = cint(11) +const DAY_6* = cint(12) +const DAY_7* = cint(13) +const ABDAY_1* = cint(14) +const ABDAY_2* = cint(15) +const ABDAY_3* = cint(16) +const ABDAY_4* = cint(17) +const ABDAY_5* = cint(18) +const ABDAY_6* = cint(19) +const ABDAY_7* = cint(20) +const MON_1* = cint(21) +const MON_2* = cint(22) +const MON_3* = cint(23) +const MON_4* = cint(24) +const MON_5* = cint(25) +const MON_6* = cint(26) +const MON_7* = cint(27) +const MON_8* = cint(28) +const MON_9* = cint(29) +const MON_10* = cint(30) +const MON_11* = cint(31) +const MON_12* = cint(32) +const ABMON_1* = cint(33) +const ABMON_2* = cint(34) +const ABMON_3* = cint(35) +const ABMON_4* = cint(36) +const ABMON_5* = cint(37) +const ABMON_6* = cint(38) +const ABMON_7* = cint(39) +const ABMON_8* = cint(40) +const ABMON_9* = cint(41) +const ABMON_10* = cint(42) +const ABMON_11* = cint(43) +const ABMON_12* = cint(44) +const ERA* = cint(45) +const ERA_D_FMT* = cint(46) +const ERA_D_T_FMT* = cint(47) +const ERA_T_FMT* = cint(48) +const ALT_DIGITS* = cint(49) +const RADIXCHAR* = cint(50) +const THOUSEP* = cint(51) +const YESEXPR* = cint(52) +const NOEXPR* = cint(53) +const CRNCYSTR* = cint(56) + +# +const LC_ALL* = cint(0) +const LC_COLLATE* = cint(1) +const LC_CTYPE* = cint(2) +const LC_MESSAGES* = cint(6) +const LC_MONETARY* = cint(3) +const LC_NUMERIC* = cint(4) +const LC_TIME* = cint(5) + +# +const IPPORT_RESERVED* = cint(1024) +const HOST_NOT_FOUND* = cint(1) +const NO_DATA* = cint(4) +const NO_RECOVERY* = cint(3) +const TRY_AGAIN* = cint(2) +const AI_PASSIVE* = cint(1) +const AI_CANONNAME* = cint(2) +const AI_NUMERICHOST* = cint(4) +const AI_NUMERICSERV* = cint(8) +const AI_V4MAPPED* = cint(2048) +const AI_ALL* = cint(256) +const AI_ADDRCONFIG* = cint(1024) +const NI_NOFQDN* = cint(1) +const NI_NUMERICHOST* = cint(2) +const NI_NAMEREQD* = cint(4) +const NI_NUMERICSERV* = cint(8) +const NI_NUMERICSCOPE* = cint(32) +const NI_DGRAM* = cint(16) +const EAI_AGAIN* = cint(2) +const EAI_BADFLAGS* = cint(3) +const EAI_FAIL* = cint(4) +const EAI_FAMILY* = cint(5) +const EAI_MEMORY* = cint(6) +const EAI_NONAME* = cint(8) +const EAI_SERVICE* = cint(9) +const EAI_SOCKTYPE* = cint(10) +const EAI_SYSTEM* = cint(11) +const EAI_OVERFLOW* = cint(14) + +# +const IF_NAMESIZE* = cint(16) + +# +const IPPROTO_IP* = cint(0) +const IPPROTO_IPV6* = cint(41) +const IPPROTO_ICMP* = cint(1) +const IPPROTO_RAW* = cint(255) +const IPPROTO_TCP* = cint(6) +const IPPROTO_UDP* = cint(17) +const INADDR_ANY* = InAddrScalar(0) +const INADDR_LOOPBACK* = InAddrScalar(2130706433) +const INADDR_BROADCAST* = InAddrScalar(-1) +const INET_ADDRSTRLEN* = cint(16) +const INET6_ADDRSTRLEN* = cint(46) +const IPV6_JOIN_GROUP* = cint(12) +const IPV6_LEAVE_GROUP* = cint(13) +const IPV6_MULTICAST_HOPS* = cint(10) +const IPV6_MULTICAST_IF* = cint(9) +const IPV6_MULTICAST_LOOP* = cint(11) +const IPV6_UNICAST_HOPS* = cint(4) +const IPV6_V6ONLY* = cint(27) + +# +const TCP_NODELAY* = cint(1) + +# + +# +const POLLIN* = cshort(1) +const POLLRDNORM* = cshort(64) +const POLLRDBAND* = cshort(128) +const POLLPRI* = cshort(2) +const POLLOUT* = cshort(4) +const POLLWRNORM* = cshort(4) +const POLLWRBAND* = cshort(256) +const POLLERR* = cshort(8) +const POLLHUP* = cshort(16) +const POLLNVAL* = cshort(32) + +# +const PTHREAD_CREATE_DETACHED* = cint(0) +const PTHREAD_CREATE_JOINABLE* = cint(1) +const PTHREAD_EXPLICIT_SCHED* = cint(2) +const PTHREAD_INHERIT_SCHED* = cint(1) +const PTHREAD_SCOPE_PROCESS* = cint(0) +const PTHREAD_SCOPE_SYSTEM* = cint(1) + +# +const SCHED_FIFO* = cint(1) +const SCHED_RR* = cint(2) +const SCHED_OTHER* = cint(0) + +# + +# +const SIGEV_NONE* = cint(1) +const SIGEV_SIGNAL* = cint(2) +const SIGEV_THREAD* = cint(3) +const SIGABRT* = cint(6) +const SIGALRM* = cint(14) +const SIGBUS* = cint(10) +const SIGCHLD* = cint(20) +const SIGCONT* = cint(19) +const SIGFPE* = cint(8) +const SIGHUP* = cint(1) +const SIGILL* = cint(4) +const SIGINT* = cint(2) +const SIGKILL* = cint(9) +const SIGPIPE* = cint(13) +const SIGQUIT* = cint(3) +const SIGSEGV* = cint(11) +const SIGSTOP* = cint(17) +const SIGTERM* = cint(15) +const SIGTSTP* = cint(18) +const SIGTTIN* = cint(21) +const SIGTTOU* = cint(22) +const SIGUSR1* = cint(30) +const SIGUSR2* = cint(31) +const SIGPOLL* = cint(23) +const SIGPROF* = cint(27) +const SIGSYS* = cint(12) +const SIGTRAP* = cint(5) +const SIGURG* = cint(16) +const SIGVTALRM* = cint(26) +const SIGXCPU* = cint(24) +const SIGXFSZ* = cint(25) +const SA_NOCLDSTOP* = cint(1) +const SIG_BLOCK* = cint(1) +const SIG_UNBLOCK* = cint(2) +const SIG_SETMASK* = cint(0) +const SS_ONSTACK* = cint(1) +const SS_DISABLE* = cint(2) +const MINSIGSTKSZ* = cint(2048) +const SIGSTKSZ* = cint(8192) +const SIG_DFL* = cast[Sighandler](0) +const SIG_ERR* = cast[Sighandler](-1) +const SIG_IGN* = cast[Sighandler](1) + +# + +# + +# + +# +const FD_SETSIZE* = cint(64) + +# +const MSG_CTRUNC* = cint(32) +const MSG_DONTROUTE* = cint(4) +const MSG_EOR* = cint(8) +const MSG_OOB* = cint(1) +const SCM_RIGHTS* = cint(1) +const SO_ACCEPTCONN* = cint(2) +const SO_BROADCAST* = cint(32) +const SO_DEBUG* = cint(1) +const SO_DONTROUTE* = cint(16) +const SO_ERROR* = cint(4103) +const SO_KEEPALIVE* = cint(8) +const SO_LINGER* = cint(128) +const SO_OOBINLINE* = cint(256) +const SO_RCVBUF* = cint(4098) +const SO_RCVLOWAT* = cint(4100) +const SO_RCVTIMEO* = cint(4102) +const SO_REUSEADDR* = cint(4) +const SO_SNDBUF* = cint(4097) +const SO_SNDLOWAT* = cint(4099) +const SO_SNDTIMEO* = cint(4101) +const SO_TYPE* = cint(4104) +const SOCK_DGRAM* = cint(2) +const SOCK_RAW* = cint(3) +const SOCK_SEQPACKET* = cint(5) +const SOCK_STREAM* = cint(1) +const SOL_SOCKET* = cint(65535) +const SOMAXCONN* = cint(128) +const SO_REUSEPORT* = cint(512) +const MSG_NOSIGNAL* = cint(131072) +const MSG_PEEK* = cint(2) +const MSG_TRUNC* = cint(16) +const MSG_WAITALL* = cint(64) +const AF_INET* = TSa_Family(2) +const AF_INET6* = TSa_Family(28) +const AF_UNIX* = TSa_Family(1) +const AF_UNSPEC* = TSa_Family(0) +const SHUT_RD* = cint(0) +const SHUT_RDWR* = cint(2) +const SHUT_WR* = cint(1) + +# +const S_IFBLK* = cint(24576) +const S_IFCHR* = cint(8192) +const S_IFDIR* = cint(16384) +const S_IFIFO* = cint(4096) +const S_IFLNK* = cint(40960) +const S_IFMT* = cint(61440) +const S_IFREG* = cint(32768) +const S_IFSOCK* = cint(49152) +const S_IRGRP* = cint(32) +const S_IROTH* = cint(4) +const S_IRUSR* = cint(256) +const S_IRWXG* = cint(56) +const S_IRWXO* = cint(7) +const S_IRWXU* = cint(448) +const S_ISGID* = cint(1024) +const S_ISUID* = cint(2048) +const S_ISVTX* = cint(512) +const S_IWGRP* = cint(16) +const S_IWOTH* = cint(2) +const S_IWUSR* = cint(128) +const S_IXGRP* = cint(8) +const S_IXOTH* = cint(1) +const S_IXUSR* = cint(64) + +# +const ST_RDONLY* = cint(1) +const ST_NOSUID* = cint(2) + +# +const WNOHANG* = cint(1) +const WUNTRACED* = cint(2) + +# +const POSIX_SPAWN_RESETIDS* = cint(1) +const POSIX_SPAWN_SETPGROUP* = cint(2) +const POSIX_SPAWN_SETSCHEDPARAM* = cint(4) +const POSIX_SPAWN_SETSCHEDULER* = cint(8) +const POSIX_SPAWN_SETSIGDEF* = cint(16) +const POSIX_SPAWN_SETSIGMASK* = cint(32) + +# +const IOFBF* = cint(0) +const IONBF* = cint(2) + +# +const CLOCKS_PER_SEC* = clong(100) +const CLOCK_REALTIME* = cint(1) +const TIMER_ABSTIME* = cint(4) +const CLOCK_MONOTONIC* = cint(4) + +# +const F_OK* = cint(0) +const R_OK* = cint(4) +const W_OK* = cint(2) +const X_OK* = cint(1) +const F_LOCK* = cint(1) +const F_TEST* = cint(3) +const F_TLOCK* = cint(2) +const F_ULOCK* = cint(0) +const PC_2_SYMLINKS* = cint(13) +const PC_ALLOC_SIZE_MIN* = cint(15) +const PC_ASYNC_IO* = cint(9) +const PC_CHOWN_RESTRICTED* = cint(6) +const PC_FILESIZEBITS* = cint(12) +const PC_LINK_MAX* = cint(0) +const PC_MAX_CANON* = cint(1) +const PC_MAX_INPUT* = cint(2) +const PC_NAME_MAX* = cint(3) +const PC_NO_TRUNC* = cint(7) +const PC_PATH_MAX* = cint(4) +const PC_PIPE_BUF* = cint(5) +const PC_PRIO_IO* = cint(10) +const PC_REC_INCR_XFER_SIZE* = cint(16) +const PC_REC_MIN_XFER_SIZE* = cint(18) +const PC_REC_XFER_ALIGN* = cint(19) +const PC_SYMLINK_MAX* = cint(14) +const PC_SYNC_IO* = cint(11) +const PC_VDISABLE* = cint(8) +const SC_2_C_BIND* = cint(108) +const SC_2_C_DEV* = cint(109) +const SC_2_CHAR_TERM* = cint(107) +const SC_2_FORT_DEV* = cint(110) +const SC_2_FORT_RUN* = cint(111) +const SC_2_LOCALEDEF* = cint(112) +const SC_2_PBS* = cint(113) +const SC_2_PBS_ACCOUNTING* = cint(114) +const SC_2_PBS_CHECKPOINT* = cint(115) +const SC_2_PBS_LOCATE* = cint(116) +const SC_2_PBS_MESSAGE* = cint(117) +const SC_2_PBS_TRACK* = cint(118) +const SC_2_SW_DEV* = cint(119) +const SC_2_UPE* = cint(120) +const SC_2_VERSION* = cint(121) +const SC_ADVISORY_INFO* = cint(54) +const SC_AIO_LISTIO_MAX* = cint(34) +const SC_AIO_MAX* = cint(35) +const SC_AIO_PRIO_DELTA_MAX* = cint(36) +const SC_ARG_MAX* = cint(0) +const SC_ASYNCHRONOUS_IO* = cint(21) +const SC_ATEXIT_MAX* = cint(55) +const SC_BARRIERS* = cint(56) +const SC_BC_BASE_MAX* = cint(57) +const SC_BC_DIM_MAX* = cint(58) +const SC_BC_SCALE_MAX* = cint(59) +const SC_BC_STRING_MAX* = cint(60) +const SC_CHILD_MAX* = cint(1) +const SC_CLK_TCK* = cint(2) +const SC_CLOCK_SELECTION* = cint(61) +const SC_COLL_WEIGHTS_MAX* = cint(62) +const SC_CPUTIME* = cint(63) +const SC_DELAYTIMER_MAX* = cint(37) +const SC_EXPR_NEST_MAX* = cint(64) +const SC_FSYNC* = cint(22) +const SC_GETGR_R_SIZE_MAX* = cint(50) +const SC_GETPW_R_SIZE_MAX* = cint(51) +const SC_HOST_NAME_MAX* = cint(65) +const SC_IOV_MAX* = cint(66) +const SC_IPV6* = cint(67) +const SC_JOB_CONTROL* = cint(5) +const SC_LINE_MAX* = cint(68) +const SC_LOGIN_NAME_MAX* = cint(52) +const SC_MAPPED_FILES* = cint(23) +const SC_MEMLOCK* = cint(24) +const SC_MEMLOCK_RANGE* = cint(25) +const SC_MEMORY_PROTECTION* = cint(26) +const SC_MESSAGE_PASSING* = cint(27) +const SC_MONOTONIC_CLOCK* = cint(69) +const SC_MQ_OPEN_MAX* = cint(13) +const SC_MQ_PRIO_MAX* = cint(14) +const SC_NGROUPS_MAX* = cint(3) +const SC_OPEN_MAX* = cint(4) +const SC_PAGE_SIZE* = cint(8) +const SC_PRIORITIZED_IO* = cint(28) +const SC_PRIORITY_SCHEDULING* = cint(101) +const SC_RAW_SOCKETS* = cint(70) +const SC_RE_DUP_MAX* = cint(73) +const SC_READER_WRITER_LOCKS* = cint(71) +const SC_REALTIME_SIGNALS* = cint(29) +const SC_REGEXP* = cint(72) +const SC_RTSIG_MAX* = cint(15) +const SC_SAVED_IDS* = cint(6) +const SC_SEM_NSEMS_MAX* = cint(16) +const SC_SEM_VALUE_MAX* = cint(17) +const SC_SEMAPHORES* = cint(30) +const SC_SHARED_MEMORY_OBJECTS* = cint(31) +const SC_SHELL* = cint(74) +const SC_SIGQUEUE_MAX* = cint(18) +const SC_SPAWN* = cint(75) +const SC_SPIN_LOCKS* = cint(76) +const SC_SPORADIC_SERVER* = cint(77) +const SC_SS_REPL_MAX* = cint(78) +const SC_STREAM_MAX* = cint(100) +const SC_SYMLOOP_MAX* = cint(79) +const SC_SYNCHRONIZED_IO* = cint(32) +const SC_THREAD_ATTR_STACKADDR* = cint(43) +const SC_THREAD_ATTR_STACKSIZE* = cint(44) +const SC_THREAD_CPUTIME* = cint(80) +const SC_THREAD_DESTRUCTOR_ITERATIONS* = cint(53) +const SC_THREAD_KEYS_MAX* = cint(38) +const SC_THREAD_PRIO_INHERIT* = cint(46) +const SC_THREAD_PRIO_PROTECT* = cint(47) +const SC_THREAD_PRIORITY_SCHEDULING* = cint(45) +const SC_THREAD_PROCESS_SHARED* = cint(48) +const SC_THREAD_SAFE_FUNCTIONS* = cint(49) +const SC_THREAD_SPORADIC_SERVER* = cint(81) +const SC_THREAD_STACK_MIN* = cint(39) +const SC_THREAD_THREADS_MAX* = cint(40) +const SC_THREADS* = cint(42) +const SC_TIMEOUTS* = cint(82) +const SC_TIMER_MAX* = cint(19) +const SC_TIMERS* = cint(33) +const SC_TRACE* = cint(83) +const SC_TRACE_EVENT_FILTER* = cint(84) +const SC_TRACE_EVENT_NAME_MAX* = cint(85) +const SC_TRACE_INHERIT* = cint(86) +const SC_TRACE_LOG* = cint(87) +const SC_TRACE_NAME_MAX* = cint(88) +const SC_TRACE_SYS_MAX* = cint(89) +const SC_TRACE_USER_EVENT_MAX* = cint(90) +const SC_TTY_NAME_MAX* = cint(41) +const SC_TYPED_MEMORY_OBJECTS* = cint(91) +const SC_TZNAME_MAX* = cint(20) +const SC_V6_ILP32_OFF32* = cint(92) +const SC_V6_ILP32_OFFBIG* = cint(93) +const SC_V6_LP64_OFF64* = cint(94) +const SC_V6_LPBIG_OFFBIG* = cint(95) +const SC_VERSION* = cint(7) +const SC_XBS5_ILP32_OFF32* = cint(92) +const SC_XBS5_ILP32_OFFBIG* = cint(93) +const SC_XBS5_LP64_OFF64* = cint(94) +const SC_XBS5_LPBIG_OFFBIG* = cint(95) +const SC_XOPEN_CRYPT* = cint(96) +const SC_XOPEN_ENH_I18N* = cint(97) +const SC_XOPEN_LEGACY* = cint(98) +const SC_XOPEN_REALTIME* = cint(99) +const SC_XOPEN_REALTIME_THREADS* = cint(102) +const SC_XOPEN_SHM* = cint(103) +const SC_XOPEN_STREAMS* = cint(104) +const SC_XOPEN_UNIX* = cint(105) +const SC_XOPEN_VERSION* = cint(106) +const SC_NPROCESSORS_ONLN* = cint(10) +const SEEK_SET* = cint(0) +const SEEK_CUR* = cint(1) +const SEEK_END* = cint(2) diff --git a/lib/pure/dynlib.nim b/lib/pure/dynlib.nim index 5bd06f6fb323..d030ad532e94 100644 --- a/lib/pure/dynlib.nim +++ b/lib/pure/dynlib.nim @@ -137,6 +137,28 @@ when defined(posix): proc symAddr(lib: LibHandle, name: cstring): pointer = return dlsym(lib, name) +elif defined(nintendoswitch): + # + # ========================================================================= + # Nintendo switch DevkitPro sdk does not have these. Raise an error if called. + # ========================================================================= + # + + proc dlclose(lib: LibHandle) = + raise newException(OSError, "dlclose not implemented on Nintendo Switch!") + proc dlopen(path: cstring, mode: int): LibHandle = + raise newException(OSError, "dlopen not implemented on Nintendo Switch!") + proc dlsym(lib: LibHandle, name: cstring): pointer = + raise newException(OSError, "dlsym not implemented on Nintendo Switch!") + proc loadLib(path: string, global_symbols=false): LibHandle = + raise newException(OSError, "loadLib not implemented on Nintendo Switch!") + proc loadLib(): LibHandle = + raise newException(OSError, "loadLib not implemented on Nintendo Switch!") + proc unloadLib(lib: LibHandle) = + raise newException(OSError, "unloadLib not implemented on Nintendo Switch!") + proc symAddr(lib: LibHandle, name: cstring): pointer = + raise newException(OSError, "symAddr not implemented on Nintendo Switch!") + elif defined(windows) or defined(dos): # # ======================================================================= diff --git a/lib/pure/os.nim b/lib/pure/os.nim index 3bc87728bf0f..5997451769ba 100644 --- a/lib/pure/os.nim +++ b/lib/pure/os.nim @@ -819,7 +819,8 @@ iterator walkDir*(dir: string; relative=false): tuple[kind: PathComponent, path: y = dir / y var k = pcFile - when defined(linux) or defined(macosx) or defined(bsd) or defined(genode): + when defined(linux) or defined(macosx) or + defined(bsd) or defined(genode) or defined(nintendoswitch): if x.d_type != DT_UNKNOWN: if x.d_type == DT_DIR: k = pcDir if x.d_type == DT_LNK: @@ -1283,6 +1284,13 @@ elif defined(windows): if i < ownArgv.len and i >= 0: return TaintedString(ownArgv[i]) raise newException(IndexError, "invalid index") +elif defined(nintendoswitch): + proc paramStr*(i: int): TaintedString {.tags: [ReadIOEffect].} = + raise newException(OSError, "paramStr is not implemented on Nintendo Switch") + + proc paramCount*(): int {.tags: [ReadIOEffect].} = + raise newException(OSError, "paramCount is not implemented on Nintendo Switch") + elif not defined(createNimRtl) and not(defined(posix) and appType == "lib") and not defined(genode): @@ -1439,7 +1447,7 @@ proc getAppFilename*(): string {.rtl, extern: "nos$1", tags: [ReadIOEffect].} = result = getApplAux("/proc/self/exe") elif defined(solaris): result = getApplAux("/proc/" & $getpid() & "/path/a.out") - elif defined(genode): + elif defined(genode) or defined(nintendoswitch): raiseOSError(OSErrorCode(-1), "POSIX command line not supported") elif defined(freebsd) or defined(dragonfly): result = getApplFreebsd() diff --git a/lib/pure/ospaths.nim b/lib/pure/ospaths.nim index c0d3ef51273a..905a659255bb 100644 --- a/lib/pure/ospaths.nim +++ b/lib/pure/ospaths.nim @@ -597,7 +597,7 @@ proc quoteShellPosix*(s: string): string {.noSideEffect, rtl, extern: "nosp$1".} else: return "'" & s.replace("'", "'\"'\"'") & "'" -when defined(windows) or defined(posix): +when defined(windows) or defined(posix) or defined(nintendoswitch): proc quoteShell*(s: string): string {.noSideEffect, rtl, extern: "nosp$1".} = ## Quote ``s``, so it can be safely passed to shell. when defined(windows): diff --git a/lib/pure/selectors.nim b/lib/pure/selectors.nim index 640df8282a9b..935250e085c3 100644 --- a/lib/pure/selectors.nim +++ b/lib/pure/selectors.nim @@ -312,6 +312,8 @@ else: include ioselects/ioselectors_poll # need to replace it with event ports elif defined(genode): include ioselects/ioselectors_select # TODO: use the native VFS layer + elif defined(nintendoswitch): + include ioselects/ioselectors_select else: include ioselects/ioselectors_poll diff --git a/lib/system/ansi_c.nim b/lib/system/ansi_c.nim index 0bac979e722c..52cb15e39b79 100644 --- a/lib/system/ansi_c.nim +++ b/lib/system/ansi_c.nim @@ -45,7 +45,7 @@ when defined(windows): SIGTERM = cint(15) elif defined(macosx) or defined(linux) or defined(freebsd) or defined(openbsd) or defined(netbsd) or defined(solaris) or - defined(dragonfly): + defined(dragonfly) or defined(nintendoswitch): const SIGABRT = cint(6) SIGFPE = cint(8) diff --git a/lib/system/dyncalls.nim b/lib/system/dyncalls.nim index f1ff307da1bc..8fb69482902d 100644 --- a/lib/system/dyncalls.nim +++ b/lib/system/dyncalls.nim @@ -167,6 +167,24 @@ elif defined(genode): proc nimGetProcAddr(lib: LibHandle, name: cstring): ProcAddr {. error: "nimGetProcAddr not implemented".} +elif defined(nintendoswitch): + proc nimUnloadLibrary(lib: LibHandle) = + stderr.rawWrite("nimUnLoadLibrary not implemented") + stderr.rawWrite("\n") + quit(1) + + proc nimLoadLibrary(path: string): LibHandle = + stderr.rawWrite("nimLoadLibrary not implemented") + stderr.rawWrite("\n") + quit(1) + + + proc nimGetProcAddr(lib: LibHandle, name: cstring): ProcAddr = + stderr.rawWrite("nimGetProAddr not implemented") + stderr.write(name) + stderr.rawWrite("\n") + quit(1) + else: {.error: "no implementation for dyncalls".} diff --git a/lib/system/osalloc.nim b/lib/system/osalloc.nim index a63eadf8eccf..048077b504aa 100644 --- a/lib/system/osalloc.nim +++ b/lib/system/osalloc.nim @@ -80,6 +80,43 @@ when defined(emscripten): elif defined(genode): include genode/alloc # osAllocPages, osTryAllocPages, osDeallocPages +elif defined(nintendoswitch): + import nintendoswitch/switch_memory + + var + stack: pointer + + proc alignSize(size: int): int = + (size + 0x00000FFF) and not 0x00000FFF + + proc freeMem(p: pointer, msize: int) = + let size = alignSize(msize) + discard svcUnmapMemory(p, stack, size.uint64) + virtmemFreeMap(p, size.csize) + free(stack) + + proc osAllocPages(msize: int): pointer {.inline.} = + let size = alignSize(msize) + stack = memalign(0x1000, size) + result = virtmemReserveMap(size.csize) + let rc = svcMapMemory(result, stack, size.uint64) + if rc.uint32 != 0: + freeMem(result, size) + raiseOutOfMem() + + proc osTryAllocPages(msize: int): pointer {.inline.} = + let size = alignSize(msize) + stack = memalign(0x1000, size) + result = virtmemReserveMap(size.csize) + let rc = svcMapMemory(result, stack, size.uint64) + if rc.uint32 != 0: + freeMem(result, size) + result = nil + + proc osDeallocPages(p: pointer, size: int) {.inline.} = + when reallyOsDealloc: + freeMem(p, size) + elif defined(posix): const PROT_READ = 1 # page can be read diff --git a/lib/system/platforms.nim b/lib/system/platforms.nim index b561cd3ba265..31d2cb01e183 100644 --- a/lib/system/platforms.nim +++ b/lib/system/platforms.nim @@ -37,7 +37,7 @@ type none, dos, windows, os2, linux, morphos, skyos, solaris, irix, netbsd, freebsd, openbsd, aix, palmos, qnx, amiga, atari, netware, macos, macosx, haiku, android, js, nimVM, - standalone + standalone, nintendoswitch const targetOS* = when defined(windows): OsPlatform.windows @@ -64,6 +64,7 @@ const elif defined(js): OsPlatform.js elif defined(nimVM): OsPlatform.nimVM elif defined(standalone): OsPlatform.standalone + elif defined(nintendoswitch): OsPlatform.nintendoswitch else: OsPlatform.none ## the OS this program will run on. diff --git a/lib/system/sysio.nim b/lib/system/sysio.nim index 86b2902308f4..f3a576be094b 100644 --- a/lib/system/sysio.nim +++ b/lib/system/sysio.nim @@ -419,7 +419,7 @@ proc setStdIoUnbuffered() = when declared(stdout): proc echoBinSafe(args: openArray[string]) {.compilerProc.} = # flockfile deadlocks some versions of Android 5.x.x - when not defined(windows) and not defined(android): + when not defined(windows) and not defined(android) and not defined(nintendoswitch): proc flockfile(f: File) {.importc, noDecl.} proc funlockfile(f: File) {.importc, noDecl.} flockfile(stdout) @@ -428,7 +428,7 @@ when declared(stdout): const linefeed = "\n" # can be 1 or more chars discard c_fwrite(linefeed.cstring, linefeed.len, 1, stdout) discard c_fflush(stdout) - when not defined(windows) and not defined(android): + when not defined(windows) and not defined(android) and not defined(nintendoswitch): funlockfile(stdout) {.pop.} diff --git a/lib/system/threads.nim b/lib/system/threads.nim index c8ea03f92976..3bfaa1dc20c7 100644 --- a/lib/system/threads.nim +++ b/lib/system/threads.nim @@ -176,7 +176,7 @@ else: else: type Time = int - when defined(linux) and defined(amd64): + when (defined(linux) or defined(nintendoswitch)) and defined(amd64): type SysThread* {.importc: "pthread_t", header: "" .} = distinct culong