Merge pull request #8 from angerman/feature/add-more-archs
authorBen Gamari <ben@smart-cactus.org>
Tue, 23 Oct 2018 20:08:32 +0000 (16:08 -0400)
committerGitHub <noreply@github.com>
Tue, 23 Oct 2018 20:08:32 +0000 (16:08 -0400)
Feature/add more archs

.gitignore
.travis.yml
Compat/ResponseFile.hs [new file with mode: 0644]
Main.hs
cabal.project [new file with mode: 0644]
changelog.md
hsc2hs.cabal

index af1adf7..82f3a88 100644 (file)
@@ -1,2 +1,22 @@
-dist-install
 dist
+dist-*
+cabal-dev
+*.o
+*.hi
+*.chi
+*.chs.h
+*.dyn_o
+*.dyn_hi
+.hpc
+.hsenv
+.cabal-sandbox/
+cabal.sandbox.config
+*.prof
+*.aux
+*.hp
+*.eventlog
+.stack-work/
+cabal.project.local
+cabal.project.local~
+.HTF/
+.ghc.environment.*
index c3b66eb..a103ff1 100644 (file)
@@ -1,8 +1,8 @@
 # This Travis job script has been generated by a script via
 #
-#   runghc make_travis_yml_2.hs 'hsc2hs.cabal'
+#   runghc make_travis_yml_2.hs '-o' '.travis.yml' '--ghc-head' '--env=7.0.4:NOINSTALLEDCONSTRAINTS=true TEST=--disable-tests BENCH=--disable-benchmarks' '--env=7.2.2:TEST=--disable-tests BENCH=--disable-benchmarks' 'cabal.project'
 #
-# For more information, see https://github.com/hvr/multi-ghc-travis
+# For more information, see https://github.com/haskell-CI/haskell-ci
 #
 language: c
 sudo: false
@@ -28,38 +28,42 @@ before_cache:
 
 matrix:
   include:
-    - compiler: "ghc-7.0.4"
-      # can't build the testsuites dependencies with 7.0
-      env: INSTALLED=false TEST=--disable-tests BENCH=--disable-benchmarks
-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-head,ghc-7.0.4], sources: [hvr-ghc]}}
-    - compiler: "ghc-7.2.2"
-    # can't build the testsuites dependencies with 7.2
-      env: TEST=--disable-tests BENCH=--disable-benchmarks
-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-head,ghc-7.2.2], sources: [hvr-ghc]}}
-    - compiler: "ghc-7.4.2"
+    - compiler: "ghc-8.6.1"
     # env: TEST=--disable-tests BENCH=--disable-benchmarks
-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-head,ghc-7.4.2], sources: [hvr-ghc]}}
-    - compiler: "ghc-7.6.3"
+      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.6.1], sources: [hvr-ghc]}}
+    - compiler: "ghc-8.4.4"
     # env: TEST=--disable-tests BENCH=--disable-benchmarks
-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-head,ghc-7.6.3], sources: [hvr-ghc]}}
-    - compiler: "ghc-7.8.4"
+      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.4.4], sources: [hvr-ghc]}}
+    - compiler: "ghc-8.2.2"
+    # env: TEST=--disable-tests BENCH=--disable-benchmarks
+      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.2.2], sources: [hvr-ghc]}}
+    - compiler: "ghc-8.0.2"
     # env: TEST=--disable-tests BENCH=--disable-benchmarks
-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-head,ghc-7.8.4], sources: [hvr-ghc]}}
+      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.0.2], sources: [hvr-ghc]}}
     - compiler: "ghc-7.10.3"
     # env: TEST=--disable-tests BENCH=--disable-benchmarks
-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-head,ghc-7.10.3], sources: [hvr-ghc]}}
-    - compiler: "ghc-8.0.2"
+      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-7.10.3], sources: [hvr-ghc]}}
+    - compiler: "ghc-7.8.4"
     # env: TEST=--disable-tests BENCH=--disable-benchmarks
-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-head,ghc-8.0.2], sources: [hvr-ghc]}}
-    - compiler: "ghc-8.2.2"
+      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-7.8.4], sources: [hvr-ghc]}}
+    - compiler: "ghc-7.6.3"
     # env: TEST=--disable-tests BENCH=--disable-benchmarks
-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-head,ghc-8.2.2], sources: [hvr-ghc]}}
-    - compiler: "ghc-8.4.1"
+      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-7.6.3], sources: [hvr-ghc]}}
+    - compiler: "ghc-7.4.2"
+    # env: TEST=--disable-tests BENCH=--disable-benchmarks
+      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-7.4.2], sources: [hvr-ghc]}}
+    - compiler: "ghc-7.2.2"
+      env: TEST=--disable-tests BENCH=--disable-benchmarks
+      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-7.2.2], sources: [hvr-ghc]}}
+    - compiler: "ghc-7.0.4"
+      env: NOINSTALLEDCONSTRAINTS=true TEST=--disable-tests BENCH=--disable-benchmarks
+      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-7.0.4], sources: [hvr-ghc]}}
+    - compiler: "ghc-head"
       env: GHCHEAD=true
-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-head,ghc-8.4.1], sources: [hvr-ghc]}}
+      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-head,ghc-head], sources: [hvr-ghc]}}
 
   allow_failures:
-    - compiler: "ghc-8.4.1"
+    - compiler: "ghc-head"
 
 before_install:
   - HC=${CC}
@@ -77,7 +81,8 @@ install:
   - BENCH=${BENCH---enable-benchmarks}
   - TEST=${TEST---enable-tests}
   - HADDOCK=${HADDOCK-true}
-  - INSTALLED=${INSTALLED-true}
+  - UNCONSTRAINED=${UNCONSTRAINED-true}
+  - NOINSTALLEDCONSTRAINTS=${NOINSTALLEDCONSTRAINTS-false}
   - GHCHEAD=${GHCHEAD-false}
   - travis_retry cabal update -v
   - "sed -i.bak 's/^jobs:/-- jobs:/' ${HOME}/.cabal/config"
@@ -85,7 +90,8 @@ install:
   # Overlay Hackage Package Index for GHC HEAD: https://github.com/hvr/head.hackage
   - |
     if $GHCHEAD; then
-      sed -i.bak 's/-- allow-newer:.*/allow-newer: *:base, *:template-haskell, *:ghc, *:Cabal/' ${HOME}/.cabal/config
+      sed -i 's/-- allow-newer: .*/allow-newer: *:base/' ${HOME}/.cabal/config
+      for pkg in $($HCPKG list --simple-output); do pkg=$(echo $pkg | sed 's/-[^-]*$//'); sed -i "s/allow-newer: /allow-newer: *:$pkg, /" ${HOME}/.cabal/config; done
 
       echo 'repository head.hackage'                                                        >> ${HOME}/.cabal/config
       echo '   url: http://head.hackage.haskell.org/'                                       >> ${HOME}/.cabal/config
@@ -95,11 +101,16 @@ install:
       echo '              8f79fd2389ab2967354407ec852cbe73f2e8635793ac446d09461ffb99527f6e' >> ${HOME}/.cabal/config
       echo '   key-threshold: 3'                                                            >> ${HOME}/.cabal.config
 
+      grep -Ev -- '^\s*--' ${HOME}/.cabal/config | grep -Ev '^\s*$'
+
       cabal new-update head.hackage -v
     fi
   - grep -Ev -- '^\s*--' ${HOME}/.cabal/config | grep -Ev '^\s*$'
   - "printf 'packages: \".\"\\n' > cabal.project"
-  - cat cabal.project
+  - touch cabal.project.local
+  - "if ! $NOINSTALLEDCONSTRAINTS; then for pkg in $($HCPKG list --simple-output); do echo $pkg  | grep -vw -- hsc2hs | sed 's/^/constraints: /' | sed 's/-[^-]*$/ installed/' >> cabal.project.local; done; fi"
+  - cat cabal.project || true
+  - cat cabal.project.local || true
   - if [ -f "./configure.ac" ]; then
       (cd "." && autoreconf -i);
     fi
@@ -113,18 +124,18 @@ install:
 # any command which exits with a non-zero exit code causes the build to fail.
 script:
   # test that source-distributions can be generated
-  - (cd "." && cabal sdist)
-  - mv "."/dist/hsc2hs-*.tar.gz ${DISTDIR}/
+  - cabal new-sdist all
+  - mv dist-newstyle/sdist/*.tar.gz ${DISTDIR}/
   - cd ${DISTDIR} || false
   - find . -maxdepth 1 -name '*.tar.gz' -exec tar -xvf '{}' \;
   - "printf 'packages: hsc2hs-*/*.cabal\\n' > cabal.project"
-  - cat cabal.project
+  - touch cabal.project.local
+  - "if ! $NOINSTALLEDCONSTRAINTS; then for pkg in $($HCPKG list --simple-output); do echo $pkg  | grep -vw -- hsc2hs | sed 's/^/constraints: /' | sed 's/-[^-]*$/ installed/' >> cabal.project.local; done; fi"
+  - cat cabal.project || true
+  - cat cabal.project.local || true
   # this builds all libraries and executables (without tests/benchmarks)
   - cabal new-build -w ${HC} --disable-tests --disable-benchmarks all
 
-  # Build with installed constraints for packages in global-db
-  - if $INSTALLED; then echo cabal new-build -w ${HC} --disable-tests --disable-benchmarks $(${HCPKG} list --global --simple-output --names-only | sed 's/\([a-zA-Z0-9-]\{1,\}\) */--constraint="\1 installed" /g') all | sh; else echo "Not building with installed constraints"; fi
-
   # build & run tests, build benchmarks
   - cabal new-build -w ${HC} ${TEST} ${BENCH} all
   - if [ "x$TEST" = "x--enable-tests" ]; then cabal new-test -w ${HC} ${TEST} ${BENCH} all; fi
@@ -132,5 +143,8 @@ script:
   # cabal check
   - (cd hsc2hs-* && cabal check)
 
-# REGENDATA ["hsc2hs.cabal"]
+  # Build without installed constraints for packages in global-db
+  - if $UNCONSTRAINED; then rm -f cabal.project.local; echo cabal new-build -w ${HC} --disable-tests --disable-benchmarks all; else echo "Not building without installed constraints"; fi
+
+# REGENDATA ["-o",".travis.yml","--ghc-head","--env=7.0.4:NOINSTALLEDCONSTRAINTS=true TEST=--disable-tests BENCH=--disable-benchmarks","--env=7.2.2:TEST=--disable-tests BENCH=--disable-benchmarks","cabal.project"]
 # EOF
diff --git a/Compat/ResponseFile.hs b/Compat/ResponseFile.hs
new file mode 100644 (file)
index 0000000..eb8e2df
--- /dev/null
@@ -0,0 +1,118 @@
+{-# LANGUAGE CPP                 #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+
+-- taken from base-4.12.0.0's "GHC.ResponseFile"
+
+module Compat.ResponseFile ( getArgsWithResponseFiles ) where
+
+#if MIN_VERSION_base(4,12,0)
+
+import           GHC.ResponseFile   (getArgsWithResponseFiles)
+
+#else
+
+import           Control.Exception
+import           Data.Char          (isSpace)
+import           System.Environment (getArgs)
+import           System.Exit        (exitFailure)
+import           System.IO
+
+{-|
+Like 'getArgs', but can also read arguments supplied via response files.
+
+
+For example, consider a program @foo@:
+
+@
+main :: IO ()
+main = do
+  args <- getArgsWithResponseFiles
+  putStrLn (show args)
+@
+
+
+And a response file @args.txt@:
+
+@
+--one 1
+--'two' 2
+--"three" 3
+@
+
+Then the result of invoking @foo@ with @args.txt@ is:
+
+> > ./foo @args.txt
+> ["--one","1","--two","2","--three","3"]
+
+-}
+getArgsWithResponseFiles :: IO [String]
+getArgsWithResponseFiles = getArgs >>= expandResponse
+
+-- | Given a string of concatenated strings, separate each by removing
+-- a layer of /quoting/ and\/or /escaping/ of certain characters.
+--
+-- These characters are: any whitespace, single quote, double quote,
+-- and the backslash character.  The backslash character always
+-- escapes (i.e., passes through without further consideration) the
+-- character which follows.  Characters can also be escaped in blocks
+-- by quoting (i.e., surrounding the blocks with matching pairs of
+-- either single- or double-quotes which are not themselves escaped).
+--
+-- Any whitespace which appears outside of either of the quoting and
+-- escaping mechanisms, is interpreted as having been added by this
+-- special concatenation process to designate where the boundaries
+-- are between the original, un-concatenated list of strings.  These
+-- added whitespace characters are removed from the output.
+--
+-- > unescapeArgs "hello\\ \\\"world\\\"\n" == escapeArgs "hello \"world\""
+unescapeArgs :: String -> [String]
+unescapeArgs = filter (not . null) . unescape
+
+-- | Arguments which look like '@foo' will be replaced with the
+-- contents of file @foo@. A gcc-like syntax for response files arguments
+-- is expected.  This must re-constitute the argument list by doing an
+-- inverse of the escaping mechanism done by the calling-program side.
+--
+-- We quit if the file is not found or reading somehow fails.
+-- (A convenience routine for haddock or possibly other clients)
+expandResponse :: [String] -> IO [String]
+expandResponse = fmap concat . mapM expand
+  where
+    expand :: String -> IO [String]
+    expand ('@':f) = readFileExc f >>= return . unescapeArgs
+    expand x       = return [x]
+
+    readFileExc f =
+      readFile f `Control.Exception.catch` \(e :: IOException) -> do
+        hPutStrLn stderr $ "Error while expanding response file: " ++ show e
+        exitFailure
+
+data Quoting = NoneQ | SngQ | DblQ
+
+unescape :: String -> [String]
+unescape args = reverse . map reverse $ go args NoneQ False [] []
+    where
+      -- n.b., the order of these cases matters; these are cribbed from gcc
+      -- case 1: end of input
+      go []     _q    _bs   a as = a:as
+      -- case 2: back-slash escape in progress
+      go (c:cs) q     True  a as = go cs q     False (c:a) as
+      -- case 3: no back-slash escape in progress, but got a back-slash
+      go (c:cs) q     False a as
+        | '\\' == c              = go cs q     True  a     as
+      -- case 4: single-quote escaping in progress
+      go (c:cs) SngQ  False a as
+        | '\'' == c              = go cs NoneQ False a     as
+        | otherwise              = go cs SngQ  False (c:a) as
+      -- case 5: double-quote escaping in progress
+      go (c:cs) DblQ  False a as
+        | '"' == c               = go cs NoneQ False a     as
+        | otherwise              = go cs DblQ  False (c:a) as
+      -- case 6: no escaping is in progress
+      go (c:cs) NoneQ False a as
+        | isSpace c              = go cs NoneQ False []    (a:as)
+        | '\'' == c              = go cs SngQ  False a     as
+        | '"'  == c              = go cs DblQ  False a     as
+        | otherwise              = go cs NoneQ False (c:a) as
+
+#endif
diff --git a/Main.hs b/Main.hs
index 60c7276..9935eee 100644 (file)
--- a/Main.hs
+++ b/Main.hs
@@ -29,7 +29,7 @@ import Foreign
 import Foreign.C.String
 #endif
 import System.Directory         ( doesFileExist, findExecutable )
-import System.Environment       ( getProgName, getArgs )
+import System.Environment       ( getProgName )
 import System.Exit              ( ExitCode(..), exitWith )
 import System.FilePath          ( normalise, splitFileName, splitExtension )
 import System.IO
@@ -46,6 +46,7 @@ import System.FilePath          ( takeDirectory, (</>) )
 #endif
 
 import Common
+import Compat.ResponseFile         ( getArgsWithResponseFiles )
 import CrossCodegen
 import DirectCodegen
 import Flags
@@ -74,7 +75,7 @@ main = do
     prog <- getProgramName
     let header = "Usage: "++prog++" [OPTIONS] INPUT.hsc [...]\n"
         usage = usageInfo header options
-    args <- getArgs
+    args <- getArgsWithResponseFiles
     let (fs, files, errs) = getOpt Permute options args
     let mode = foldl (.) id fs emptyMode
     case mode of
diff --git a/cabal.project b/cabal.project
new file mode 100644 (file)
index 0000000..e6fdbad
--- /dev/null
@@ -0,0 +1 @@
+packages: .
index 7a211bc..b1061c5 100644 (file)
@@ -1,3 +1,13 @@
+## 0.68.4.1
+
+ - Support response files regardless of which GHC `hsc2hs` was compiled
+   with ([#15758](https://ghc.haskell.org/trac/ghc/ticket/15758))
+
+## 0.68.4
+
+ - Add support to read command line arguments supplied via response files
+   ([#13896](https://ghc.haskell.org/trac/ghc/ticket/13388))
+
 ## 0.68.2
 
  - Support GHC 8.2.1
index 02c4aee..d08cd9e 100644 (file)
@@ -1,12 +1,14 @@
+cabal-version: >=1.10
 Name: hsc2hs
-Version: 0.68.3
+Version: 0.68.4.1
+
 Copyright: 2000, Marcin Kowalczyk
 License: BSD3
 License-File: LICENSE
 Author: Marcin Kowalczyk <qrczak@knm.org.pl>
 Maintainer: ghc-devs@haskell.org
 Synopsis: A preprocessor that helps with writing Haskell bindings to C code
-Bug-Reports: https://ghc.haskell.org/trac/ghc/newticket?component=hsc2hs
+Bug-Reports: https://github.com/haskell/hsc2hs/issues
 Description:
     The hsc2hs program can be used to automate some parts of the
     process of writing Haskell bindings to C code.  It reads an
@@ -22,8 +24,7 @@ Description:
 Category: Development
 Data-Files: template-hsc.h
 build-type: Simple
-cabal-version: >=1.10
-tested-with: GHC==8.2.1, GHC==8.0.2, GHC==7.10.3, GHC==7.8.4, GHC==7.6.3, GHC==7.4.2, GHC==7.2.2, GHC==7.0.4
+tested-with: GHC==8.6.1, GHC==8.4.4, GHC==8.2.2, GHC==8.0.2, GHC==7.10.3, GHC==7.8.4, GHC==7.6.3, GHC==7.4.2, GHC==7.2.2, GHC==7.0.4
 
 extra-source-files:
   changelog.md
@@ -36,7 +37,7 @@ flag in-ghc-tree
 
 source-repository head
     Type: git
-    Location: http://git.haskell.org/hsc2hs.git
+    Location: https://github.com/haskell/hsc2hs.git
 
 Executable hsc2hs
     Default-Language: Haskell2010
@@ -50,15 +51,16 @@ Executable hsc2hs
         HSCParser
         ATTParser
         UtilsCodegen
+        Compat.ResponseFile
         Paths_hsc2hs
 
     Other-Extensions: CPP, NoMonomorphismRestriction
 
-    Build-Depends: base       >= 4   && < 5,
-                   containers >= 0.2 && < 0.6,
-                   directory  >= 1   && < 1.4,
-                   filepath   >= 1   && < 1.5,
-                   process    >= 1.1 && < 1.7
+    Build-Depends: base       >= 4.3.0 && < 5,
+                   containers >= 0.4.0 && < 0.7,
+                   directory  >= 1.1.0 && < 1.4,
+                   filepath   >= 1.2.0 && < 1.5,
+                   process    >= 1.1.0 && < 1.7
     if flag(in-ghc-tree)
        cpp-options: -DIN_GHC_TREE