File: UtilsCodegen.hs

package info (click to toggle)
ghc 9.0.2-4
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 177,780 kB
  • sloc: haskell: 494,441; ansic: 70,262; javascript: 9,423; sh: 8,537; python: 2,646; asm: 1,725; makefile: 1,333; xml: 196; cpp: 167; perl: 143; ruby: 84; lisp: 7
file content (88 lines) | stat: -rw-r--r-- 3,084 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
module UtilsCodegen where

{-
Generate the utility code for hsc2hs.

We don't want to include C headers in template-hsc.h
See GHC trac #2897
-}

import Control.Monad

import C
import Common
import Flags

withUtilsObject :: Config -> FilePath -> FilePath
                -> (FilePath -> IO a)
                -> IO a
withUtilsObject config outDir outBase f = do

    let beVerbose = cVerbose config
        flags     = cFlags config
        possiblyRemove = if cKeepFiles config
                         then flip const
                         else finallyRemove
        cUtilsName = outDir ++ outBase ++ "_hsc_utils.c"
        oUtilsName = outDir ++ outBase ++ "_hsc_utils.o"

    possiblyRemove cUtilsName $ do
        writeBinaryFile cUtilsName $ unlines $
             -- These header will cause a mismatch with any mingw-w64 header by
             -- including system headers before user headers in the hsc file.
             -- We *MUST* include user headers *BEFORE* automatic ones.  */
            [outTemplateHeaderCProg (cTemplate config),
             "",
             "#include <stddef.h>",
             "#include <string.h>",
             "#include <stdio.h>",
             "#include <stdarg.h>",
             "#include <ctype.h>",
             "",
             "int hsc_printf(const char *format, ...) {",
             "    int r;",
             "    va_list argp;",
             "    va_start(argp, format);",
             "    r = vprintf(format, argp);",
             "    va_end(argp);",
             "    return r;",
             "}",
             "",
             "int hsc_toupper(int c) {",
             "    return toupper(c);",
             "}",
             "",
             "int hsc_tolower(int c) {",
             "    return tolower(c);",
             "}",
             "",
             "int hsc_putchar(int c) {",
             "    return putchar(c);",
             "}",
             "",
             -- "void" should really be "FILE", but we aren't able to
             -- refer to "FILE" in template-hsc.h as we don't want to
             -- include <stdio.h> there. We cast to FILE * so as to
             -- allow compiling with g++.
             "int hsc_fputs(const char *s, void *stream) {",
             "    return fputs(s, (FILE *)stream);",
             "}",
             "",
             -- "void" should really be "FILE", but we aren't able to
             -- refer to "FILE" in template-hsc.h as we don't want to
             -- include <stdio.h> there. We explicitly cast to void *
             -- to allow compiling with g++.
             "void *hsc_stdout(void) {",
             "    return (void *)stdout;",
             "}"
            ]

        possiblyRemove oUtilsName $ do
           unless (cNoCompile config) $
               rawSystemL outDir (outBase ++ "_utils") ("compiling " ++ cUtilsName)
                          beVerbose
                          (cCompiler config)
                          (["-c", cUtilsName, "-o", oUtilsName] ++
                           [cFlag | CompFlag cFlag <- flags])

           f oUtilsName