1# 2# 3# Nim's Runtime Library 4# (c) Copyright 2013 Andreas Rumpf 5# 6# See the file "copying.txt", included in this 7# distribution, for details about the copyright. 8# 9 10# This module contains headers of Ansi C procs 11# and definitions of Ansi C types in Nim syntax 12# All symbols are prefixed with 'c_' to avoid ambiguities 13 14{.push hints:off, stack_trace: off, profiler: off.} 15 16proc c_memchr*(s: pointer, c: cint, n: csize_t): pointer {. 17 importc: "memchr", header: "<string.h>".} 18proc c_memcmp*(a, b: pointer, size: csize_t): cint {. 19 importc: "memcmp", header: "<string.h>", noSideEffect.} 20proc c_memcpy*(a, b: pointer, size: csize_t): pointer {. 21 importc: "memcpy", header: "<string.h>", discardable.} 22proc c_memmove*(a, b: pointer, size: csize_t): pointer {. 23 importc: "memmove", header: "<string.h>",discardable.} 24proc c_memset*(p: pointer, value: cint, size: csize_t): pointer {. 25 importc: "memset", header: "<string.h>", discardable.} 26proc c_strcmp*(a, b: cstring): cint {. 27 importc: "strcmp", header: "<string.h>", noSideEffect.} 28proc c_strlen*(a: cstring): csize_t {. 29 importc: "strlen", header: "<string.h>", noSideEffect.} 30proc c_abort*() {. 31 importc: "abort", header: "<stdlib.h>", noSideEffect, noreturn.} 32 33 34when defined(nimBuiltinSetjmp): 35 type 36 C_JmpBuf* = array[5, pointer] 37elif defined(linux) and defined(amd64): 38 type 39 C_JmpBuf* {.importc: "jmp_buf", header: "<setjmp.h>", bycopy.} = object 40 abi: array[200 div sizeof(clong), clong] 41else: 42 type 43 C_JmpBuf* {.importc: "jmp_buf", header: "<setjmp.h>".} = object 44 45 46type CSighandlerT = proc (a: cint) {.noconv.} 47when defined(windows): 48 const 49 SIGABRT* = cint(22) 50 SIGFPE* = cint(8) 51 SIGILL* = cint(4) 52 SIGINT* = cint(2) 53 SIGSEGV* = cint(11) 54 SIGTERM = cint(15) 55 SIG_DFL* = cast[CSighandlerT](0) 56elif defined(macosx) or defined(linux) or defined(freebsd) or 57 defined(openbsd) or defined(netbsd) or defined(solaris) or 58 defined(dragonfly) or defined(nintendoswitch) or defined(genode) or 59 defined(aix) or hostOS == "standalone": 60 const 61 SIGABRT* = cint(6) 62 SIGFPE* = cint(8) 63 SIGILL* = cint(4) 64 SIGINT* = cint(2) 65 SIGSEGV* = cint(11) 66 SIGTERM* = cint(15) 67 SIGPIPE* = cint(13) 68 SIG_DFL* = cast[CSighandlerT](0) 69elif defined(haiku): 70 const 71 SIGABRT* = cint(6) 72 SIGFPE* = cint(8) 73 SIGILL* = cint(4) 74 SIGINT* = cint(2) 75 SIGSEGV* = cint(11) 76 SIGTERM* = cint(15) 77 SIGPIPE* = cint(7) 78 SIG_DFL* = cast[CSighandlerT](0) 79else: 80 when defined(nimscript): 81 {.error: "SIGABRT not ported to your platform".} 82 else: 83 var 84 SIGINT* {.importc: "SIGINT", nodecl.}: cint 85 SIGSEGV* {.importc: "SIGSEGV", nodecl.}: cint 86 SIGABRT* {.importc: "SIGABRT", nodecl.}: cint 87 SIGFPE* {.importc: "SIGFPE", nodecl.}: cint 88 SIGILL* {.importc: "SIGILL", nodecl.}: cint 89 SIG_DFL* {.importc: "SIG_DFL", nodecl.}: CSighandlerT 90 when defined(macosx) or defined(linux): 91 var SIGPIPE* {.importc: "SIGPIPE", nodecl.}: cint 92 93when defined(macosx): 94 const SIGBUS* = cint(10) 95elif defined(haiku): 96 const SIGBUS* = cint(30) 97 98# "nimRawSetjmp" is defined by default for certain platforms, so we need the 99# "nimStdSetjmp" escape hatch with it. 100when defined(nimSigSetjmp): 101 proc c_longjmp*(jmpb: C_JmpBuf, retval: cint) {. 102 header: "<setjmp.h>", importc: "siglongjmp".} 103 proc c_setjmp*(jmpb: C_JmpBuf): cint = 104 proc c_sigsetjmp(jmpb: C_JmpBuf, savemask: cint): cint {. 105 header: "<setjmp.h>", importc: "sigsetjmp".} 106 c_sigsetjmp(jmpb, 0) 107elif defined(nimBuiltinSetjmp): 108 proc c_longjmp*(jmpb: C_JmpBuf, retval: cint) = 109 # Apple's Clang++ has trouble converting array names to pointers, so we need 110 # to be very explicit here. 111 proc c_builtin_longjmp(jmpb: ptr pointer, retval: cint) {. 112 importc: "__builtin_longjmp", nodecl.} 113 # The second parameter needs to be 1 and sometimes the C/C++ compiler checks it. 114 c_builtin_longjmp(unsafeAddr jmpb[0], 1) 115 proc c_setjmp*(jmpb: C_JmpBuf): cint = 116 proc c_builtin_setjmp(jmpb: ptr pointer): cint {. 117 importc: "__builtin_setjmp", nodecl.} 118 c_builtin_setjmp(unsafeAddr jmpb[0]) 119elif defined(nimRawSetjmp) and not defined(nimStdSetjmp): 120 when defined(windows): 121 # No `_longjmp()` on Windows. 122 proc c_longjmp*(jmpb: C_JmpBuf, retval: cint) {. 123 header: "<setjmp.h>", importc: "longjmp".} 124 # The Windows `_setjmp()` takes two arguments, with the second being an 125 # undocumented buffer used by the SEH mechanism for stack unwinding. 126 # Mingw-w64 has been trying to get it right for years, but it's still 127 # prone to stack corruption during unwinding, so we disable that by setting 128 # it to NULL. 129 # More details: https://github.com/status-im/nimbus-eth2/issues/3121 130 proc c_setjmp*(jmpb: C_JmpBuf): cint = 131 proc c_setjmp_win(jmpb: C_JmpBuf, ctx: pointer): cint {. 132 header: "<setjmp.h>", importc: "_setjmp".} 133 c_setjmp_win(jmpb, nil) 134 else: 135 proc c_longjmp*(jmpb: C_JmpBuf, retval: cint) {. 136 header: "<setjmp.h>", importc: "_longjmp".} 137 proc c_setjmp*(jmpb: C_JmpBuf): cint {. 138 header: "<setjmp.h>", importc: "_setjmp".} 139else: 140 proc c_longjmp*(jmpb: C_JmpBuf, retval: cint) {. 141 header: "<setjmp.h>", importc: "longjmp".} 142 proc c_setjmp*(jmpb: C_JmpBuf): cint {. 143 header: "<setjmp.h>", importc: "setjmp".} 144 145proc c_signal*(sign: cint, handler: CSighandlerT): CSighandlerT {. 146 importc: "signal", header: "<signal.h>", discardable.} 147proc c_raise*(sign: cint): cint {.importc: "raise", header: "<signal.h>".} 148 149type 150 CFile {.importc: "FILE", header: "<stdio.h>", 151 incompleteStruct.} = object 152 CFilePtr* = ptr CFile ## The type representing a file handle. 153 154# duplicated between io and ansi_c 155const stdioUsesMacros = (defined(osx) or defined(freebsd) or defined(dragonfly)) and not defined(emscripten) 156const stderrName = when stdioUsesMacros: "__stderrp" else: "stderr" 157const stdoutName = when stdioUsesMacros: "__stdoutp" else: "stdout" 158const stdinName = when stdioUsesMacros: "__stdinp" else: "stdin" 159 160var 161 cstderr* {.importc: stderrName, header: "<stdio.h>".}: CFilePtr 162 cstdout* {.importc: stdoutName, header: "<stdio.h>".}: CFilePtr 163 cstdin* {.importc: stdinName, header: "<stdio.h>".}: CFilePtr 164 165proc c_fprintf*(f: CFilePtr, frmt: cstring): cint {. 166 importc: "fprintf", header: "<stdio.h>", varargs, discardable.} 167proc c_printf*(frmt: cstring): cint {. 168 importc: "printf", header: "<stdio.h>", varargs, discardable.} 169 170proc c_fputs*(c: cstring, f: CFilePtr): cint {. 171 importc: "fputs", header: "<stdio.h>", discardable.} 172 173proc c_sprintf*(buf, frmt: cstring): cint {. 174 importc: "sprintf", header: "<stdio.h>", varargs, noSideEffect.} 175 # we use it only in a way that cannot lead to security issues 176 177proc c_malloc*(size: csize_t): pointer {. 178 importc: "malloc", header: "<stdlib.h>".} 179proc c_calloc*(nmemb, size: csize_t): pointer {. 180 importc: "calloc", header: "<stdlib.h>".} 181proc c_free*(p: pointer) {. 182 importc: "free", header: "<stdlib.h>".} 183proc c_realloc*(p: pointer, newsize: csize_t): pointer {. 184 importc: "realloc", header: "<stdlib.h>".} 185 186proc c_fwrite*(buf: pointer, size, n: csize_t, f: CFilePtr): cint {. 187 importc: "fwrite", header: "<stdio.h>".} 188 189proc c_fflush(f: CFilePtr): cint {. 190 importc: "fflush", header: "<stdio.h>".} 191 192proc rawWriteString*(f: CFilePtr, s: cstring, length: int) {.compilerproc, nonReloadable, inline.} = 193 # we cannot throw an exception here! 194 discard c_fwrite(s, 1, cast[csize_t](length), f) 195 discard c_fflush(f) 196 197proc rawWrite*(f: CFilePtr, s: cstring) {.compilerproc, nonReloadable, inline.} = 198 # we cannot throw an exception here! 199 discard c_fwrite(s, 1, cast[csize_t](s.len), f) 200 discard c_fflush(f) 201 202{.pop.} 203