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