ansi_c.nim 8.5 KB

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