[project @ 2000-12-28 10:34:56 by qrczak]
authorqrczak <unknown>
Thu, 28 Dec 2000 10:34:56 +0000 (10:34 +0000)
committerqrczak <unknown>
Thu, 28 Dec 2000 10:34:56 +0000 (10:34 +0000)
Implemented #undef, #error, and #let (macros to be applied to the
Haskell source, although using somewhat ugly stringified syntax).

s/hs2c/hsc2hs/

Fixed some bugs (user-supplied --cc option, macros with parameters).

ghc/docs/users_guide/utils.sgml
ghc/utils/hsc2hs/Main.hs
ghc/utils/hsc2hs/hsc2hs.sh
ghc/utils/hsc2hs/template-hsc.h

index 7aa4139..796ee90 100644 (file)
@@ -98,13 +98,13 @@ tags:
   </sect1>
 -->
 
-  <sect1 id="hs2c">
+  <sect1 id="hsc2hs">
     <title>Writing Haskell interfaces to C code:
-    <command>hs2c</command></title>
-    <indexterm><primary><command>hs2c</command></primary>
+    <command>hsc2hs</command></title>
+    <indexterm><primary><command>hsc2hs</command></primary>
     </indexterm>
 
-    <para>The <command>hs2c</command> command can be used to automate
+    <para>The <command>hsc2hs</command> command can be used to automate
     some parts of the process of writing Haskell bindings to C code.
     It reads an almost-Haskell source with embedded special
     constructs, and outputs a real Haskell file with these constructs
@@ -118,7 +118,7 @@ tags:
     two files are created when the <literal>#def</literal> construct
     is used.</para>
 
-    <para>Actually <command>hs2c</command> does not output the Haskell
+    <para>Actually <command>hsc2hs</command> does not output the Haskell
     file directly.  It creates a C program that includes the headers,
     gets automatically compiled and run. That program outputs the
     Haskell code.</para>
@@ -236,8 +236,8 @@ tags:
          <term><literal>#include "file.h"</literal></term>
          <listitem>
            <para>The specified file gets included into the C program,
-            the compiled Haskell file, and the C
-            header. <literal>&lt;HsFFI.h&gt;</literal> is included
+            the compiled Haskell file, and the C header.
+            <literal>&lt;HsFFI.h&gt;</literal> is included
             automatically.</para>
          </listitem>
        </varlistentry>
@@ -245,6 +245,7 @@ tags:
        <varlistentry>
          <term><literal>#define name</literal></term>
          <term><literal>#define name value</literal></term>
+         <term><literal>#undef name</literal></term>
          <listitem>
            <para>Similar to <literal>#include</literal>. Note that
             <literal>#includes</literal> and
@@ -254,6 +255,25 @@ tags:
        </varlistentry>
 
        <varlistentry>
+         <term><literal>#let name parameters = "definition"</literal></term>
+         <listitem>
+            <para>Defines a macro to be applied to the Haskell
+            source. Parameter names are comma-separated, not
+            inside parens. Such macro is invoked as other
+            <literal>#</literal>-constructs, starting with
+            <literal>#name</literal>. The definition will be
+            put in the C program inside parens as arguments of
+            <literal>printf</literal>. To refer to a parameter,
+            close the quote, put a parameter name and open the
+            quote again, to let C string literals concatenate.
+            Or use <literal>printf</literal>'s format directives.
+            Values of arguments must be given as strings, unless the
+            macro stringifies them itself using the C preprocessor's
+            <literal>#parameter</literal> syntax.</para>
+         </listitem>
+       </varlistentry>
+
+       <varlistentry>
          <term><literal>#option opt</literal></term>
          <listitem>
            <para>The specified Haskell compiler command-line option
@@ -286,6 +306,7 @@ tags:
          <term><literal>#elif condition</literal></term>
          <term><literal>#else</literal></term>
          <term><literal>#endif</literal></term>
+         <term><literal>#error message</literal></term>
          <listitem>
            <para>Conditional compilation directives are passed
             unmodified to the C program, C file, and C header. Putting
@@ -362,7 +383,7 @@ tags:
       <para><literal>#const</literal>, <literal>#type</literal>,
       <literal>#peek</literal>, <literal>#poke</literal> and
       <literal>#ptr</literal> are not hardwired into the
-      <command>hs2c</command>, but are defined in a C template that is
+      <command>hsc2hs</command>, but are defined in a C template that is
       included in the C program: <filename>template-hsc.h</filename>.
       Custom constructs and templates can be used too. Any
       <literal>#</literal>-construct with unknown key is expected to
index edd780d..5ff8e44 100644 (file)
@@ -1,5 +1,5 @@
 -----------------------------------------------------------------------------
--- $Id: Main.hs,v 1.2 2000/11/07 15:28:36 simonmar Exp $
+-- $Id: Main.hs,v 1.3 2000/12/28 10:34:56 qrczak Exp $
 --
 -- (originally "GlueHsc.hs" by Marcin 'Qrczak' Kowalczyk)
 --
@@ -17,6 +17,7 @@ import Directory (removeFile)
 import Parsec
 import Monad     (liftM, liftM2, when)
 import Char      (ord, intToDigit, isSpace, isAlphaNum, toUpper)
+import List      (intersperse)
 
 data Flag
     = Help
@@ -124,7 +125,7 @@ output flags name toks = let
     
     specials = [(key, arg) | Special key arg <- toks]
     
-    needsC = any (\(key, _) -> key=="def") specials
+    needsC = any (\(key, _) -> key == "def") specials
     needsH = needsC
     
     includeGuard = map fixChar outHName
@@ -178,6 +179,9 @@ output flags name toks = let
     when needsH $ writeFile outHName $
         "#ifndef "++includeGuard++"\n\
         \#define "++includeGuard++"\n\
+        \#if __GLASGOW_HASKELL__ && __GLASGOW_HASKELL__ < 409\n\
+        \#include <Rts.h>\n\
+        \#endif\n\
         \#include <HsFFI.h>\n"++
         concatMap outTokenH specials++
         "#endif\n"
@@ -195,52 +199,70 @@ outHeaderCProg :: [(String, String)] -> String
 outHeaderCProg = concatMap $ \(key, arg) -> case key of
     "include"           -> "#include "++arg++"\n"
     "define"            -> "#define "++arg++"\n"
+    "undef"             -> "#undef "++arg++"\n"
     "def"               -> case arg of
         's':'t':'r':'u':'c':'t':' ':_ -> arg++"\n"
         't':'y':'p':'e':'d':'e':'f':' ':_ -> arg++"\n"
         _ -> ""
     _ | conditional key -> "#"++key++" "++arg++"\n"
-    _                   -> ""
+    "let"               -> case break (== '=') arg of
+        (_,      "")     -> ""
+        (header, _:body) -> case break isSpace header of
+            (name, args) ->
+                "#define hsc_"++name++"("++dropWhile isSpace args++") \
+                \printf ("++joinLines body++");\n"
+    _ -> ""
+    where
+    joinLines = concat . intersperse " \\\n" . lines
 
 outHeaderHs :: Maybe String -> [(String, String)] -> String
 outHeaderHs inH toks =
+    "    hsc_begin_options();\n"++
     concatMap outSpecial toks ++
     includeH ++
     "    hsc_end_options();\n\n"
     where
     outSpecial (key, arg) = case key of
         "include" -> case inH of
-            Nothing -> out ("-#include "++arg)
+            Nothing -> outOption ("-#include "++arg)
             Just _  -> ""
         "define" -> case inH of
-            Nothing -> out ("-optc-D"++toOptD arg)
-            Just _  -> ""
-        "option" -> out arg
+            Nothing | goodForOptD arg -> outOption ("-optc-D"++toOptD arg)
+            _ -> ""
+        "option" -> outOption arg
         _ | conditional key -> "#"++key++" "++arg++"\n"
         _ -> ""
+    goodForOptD arg = case arg of
+        ""              -> True
+        c:_ | isSpace c -> True
+        '(':_           -> False
+        _:s             -> goodForOptD s
     toOptD arg = case break isSpace arg of
         (name, "")      -> name
         (name, _:value) -> name++'=':dropWhile isSpace value
     includeH = case inH of
         Nothing   -> ""
-        Just name -> out ("-#include \""++name++"\"")
-    out s = "    hsc_option (\""++showCString s++"\");\n"
+        Just name -> outOption ("-#include \""++name++"\"")
+    outOption s = "    hsc_option (\""++showCString s++"\");\n"
 
 outTokenHs :: Token -> String
 outTokenHs (Text s) = "    fputs (\""++showCString s++"\", stdout);\n"
 outTokenHs (Special key arg) = case key of
     "include"           -> ""
     "define"            -> ""
+    "undef"             -> ""
     "option"            -> ""
     "def"               -> ""
     _ | conditional key -> "#"++key++" "++arg++"\n"
+    "let"               -> ""
     _                   -> "    hsc_"++key++" ("++arg++");\n"
 
 outTokenH :: (String, String) -> String
 outTokenH (key, arg) = case key of
     "include" -> "#include "++arg++"\n"
-    "define" -> "#define " ++arg++"\n"
-    "def" -> case arg of
+    "define"  -> "#define " ++arg++"\n"
+    "undef"   -> "#undef "  ++arg++"\n"
+    "def"     -> case arg of
         's':'t':'r':'u':'c':'t':' ':_ -> arg++"\n"
         't':'y':'p':'e':'d':'e':'f':' ':_ -> arg++"\n"
         'i':'n':'l':'i':'n':'e':' ':_ ->
@@ -280,6 +302,7 @@ conditional "ifndef" = True
 conditional "elif"   = True
 conditional "else"   = True
 conditional "endif"  = True
+conditional "error"  = True
 conditional _        = False
 
 showCString :: String -> String
index ba1e64a..d757d11 100644 (file)
@@ -1 +1,9 @@
+
+for arg; do
+    case "$arg" in
+        (--cc=*) HSC2HS_EXTRA=;;
+        (--)     break;;
+    esac
+done
+
 $HSC2HS_DIR/$HS_PROG -t $HSC2HS_DIR/template-hsc.h $HSC2HS_EXTRA "$@" 
index 265dd4d..43841f0 100644 (file)
@@ -1,4 +1,8 @@
+#if __GLASGOW_HASKELL__ && __GLASGOW_HASKELL__ < 409
+#include <Rts.h>
+#endif
 #include <HsFFI.h>
+
 #include <stddef.h>
 #include <string.h>
 #include <stdio.h>
@@ -7,7 +11,18 @@
 #define offsetof(t, f) ((size_t) &((t *)0)->f)
 #endif
 
-static int hsc_options_started = 0;
+#if __GLASGOW_HASKELL__
+static int hsc_options_started;
+
+static void hsc_begin_options (void)
+{
+#if __GLASGOW_HASKELL__ < 409
+    printf ("{-# OPTIONS -optc-D__GLASGOW_HASKELL__=%d", __GLASGOW_HASKELL__);
+    hsc_options_started = 1;
+#else
+    hsc_options_started = 0;
+#endif
+}
 
 static void hsc_option (const char *s)
 {
@@ -23,6 +38,11 @@ static void hsc_end_options (void)
 {
     if (hsc_options_started) printf (" #-}\n");
 }
+#else
+#define hsc_begin_options()
+#define hsc_option(s)
+#define hsc_end_options()
+#endif
 
 #define hsc_const(x)                        \
     if ((x) < 0)                            \