How to get system page size in OCaml - ocaml

I have searched in modules Sys, Gc, and Unix, but did not find a means to get the system page size in OCaml. How can we get the system page size?
I have OCaml 4.06 and macOS 10.12.6 (Sierra)

If you just want the answer for MacOS, there is a pagesize command that you can run with Unix.open_process_in:
$ rlwrap ocaml
OCaml version 4.06.0
# #load "unix.cma";;
# Unix.open_process_in "pagesize" |> input_line |> int_of_string;;
- : int = 4096
Update
There is a POSIX command line program getconf that is quite portable, I believe. It works on macOS and all the versions of Linux I tried. You can use that instead:
$ rlwrap ocaml
OCaml version 4.06.0
# #load "unix.cma";;
# Unix.open_process_in "getconf PAGE_SIZE" |> input_line |> int_of_string;;
- : int = 4096

You can call sysconf(SC_PAGESIZE) from ocaml to get that information. You can either do that using a .c file, or using ctypes (although you'll need the value of the SC_PAGESIZE, so it might not be the best solution):
% utop -require ctypes.foreign
# open Foreign;;
# open Ctypes;;
# let sysconf = foreign "sysconf" (int #-> returning long);;
val sysconf : int -> Signed.long = <fun>
# sysconf 30;;
- : Signed.long = <long 4096>

Related

Using Haskell with Yesod to activate Pandoc

I want to use Yesod and Haskell in order to call Pandoc, to translate some format into some other format.
pandocConverted :: String -> IO String
pandocConverted input = do
(Just hIn, Just hOut, _, _) <- createProcess (proc "pandoc" []) { std_in = CreatePipe, std_out = CreatePipe }
hPutStr hIn input
converted <- hGetContents hOut
return converted
This works well. But how do I translate into a different format?
e.g. how do I call pandoc like this?
pandoc -s README -o example4.tex
or this?
pandoc -s -S -t docbook README -o example9.db
You can use the -f and -t flags to specify source and target formats when using pandoc in a pipe.
createProcess (proc "pandoc" ["-f", "markdown", "-t", "latex"])
However, since pandoc is foremostly a Haskell library (to which the pandoc executable is merely a command-line interface), it would be more idiomatic to invoke the library directly within your Yesod program, instead of using createProcess.
import Text.Pandoc
import Text.Pandoc.Error (handleError)
import Control.Arrow
pandocConverted' :: String -> String
pandocConverted' = readMarkdown def
>>> fmap (writeLaTeX def {writerReferenceLinks = True})
>>> handleError

Export user input history from OCaml utop to file

When I'm using OCaml utop every line of the input and output is printed into the console:
───┬──────────────────────────────────────────────────────────────┬───
│ Welcome to utop version 2.10.0 (using OCaml version 4.14.0)! │
└──────────────────────────────────────────────────────────────┘
Type #utop_help for help about using utop.
─( 22:17:51 )─< command 0 >─────────────────────────────{ counter: 0}─
utop # let x = 50;;
val x : int = 50
Is it possible to export each of user inputs and outputs from utop session into specific file?
Your input is saved by default at ~/.utop-history .
Isn't that enough for your purpose?
You can also change location and file size by manipulating UTop.history_file_name and other variables.

ocaml bitstring within a script

In ocaml toplevel, I can use "bitstring" package by typing the following commands:
#use "topfind";;
#camlp4o;;
#require "bitstring.syntax";;
let data = 0l;;
let bits = BITSTRING { data : 32 };;
However, if I create an OCaml script, e.g., foo.ml :
#!/usr/bin/env ocaml
#use "topfind";;
#camlp4o;;
#require "bitstring.syntax";;
let data = 0l;;
let bits = BITSTRING { data : 32 };;
And, if I run the OCaml script, I got a syntax error:
$ ./foo.ml
File "./foo.ml", line 8, characters 28-29: Error: Syntax error
What am I missing here? Why does the same code work with an interactive shell, but not with a script file?
I believe that's because script file is first parsed, and then the directives are executed, hence it cannot handle unknown (yet) syntax.
The easiest solution is to use ocamlscript :
#! /usr/bin/env ocamlscript
Ocaml.packs := [ "bitstring"; "bitstring.syntax" ]
--
let data = 0l;;
let bits = BITSTRING { data : 32 };;

Building a haskell interpreter (hint) as dynamic library, useable from C++: Missing Interpreter.dyn_hi

I want to create a haskell interpreter that I can use from C++ on linux.
I have a file FFIInterpreter.hs which implements the interpreter in haskell and exports the functions via FFI to C++.
module FFIInterpreter where
import Language.Haskell.Interpreter
import Data.IORef
import Foreign.StablePtr
import Foreign.C.Types
import Foreign.C.String
import Control.Monad
import Foreign.Marshal.Alloc
type Session = Interpreter ()
type Context = StablePtr (IORef Session)
foreign export ccall createContext :: CString -> IO Context
createContext :: CString -> IO Context
createContext name = join ((liftM doCreateContext) (peekCString name))
where
doCreateContext :: ModuleName -> IO Context
doCreateContext name
= do let session = newModule name
_ <- runInterpreter session
liftIO $ newStablePtr =<< newIORef session
newModule :: ModuleName -> Session
newModule name = loadModules [name] >> setTopLevelModules [name]
foreign export ccall freeContext :: Context -> IO ()
freeContext :: Context -> IO ()
freeContext = freeStablePtr
foreign export ccall runExpr :: Context -> CString -> IO CString
runExpr :: Context -> CString -> IO CString
runExpr env input = join ((liftM newCString) (join (((liftM liftM) doRunExpr) env (peekCString input))))
where
doRunExpr :: Context -> String -> IO String
doRunExpr env input
= do env_value <- deRefStablePtr env
tcs_value <- readIORef env_value
result <- runInterpreter (tcs_value >> eval input)
return $ either show id result
foreign export ccall freeString :: CString -> IO ()
freeString :: CString -> IO ()
freeString = Foreign.Marshal.Alloc.free
When I compile the whole project with ghc, everything works fine. I use the following command:
ghc -no-hs-main FFIInterpreter.hs main.cpp -lstdc++
But the haskell module is only a small piece of the C++ project and I don't want the whole project to depend on ghc.
So I want to build a dynamic library with ghc and then link it to the project using g++.
$ ghc -shared -fPIC FFIInterpreter.hs module_init.c -lstdc++
[1 of 1] Compiling FFIInterpreter ( FFIInterpreter.hs, FFIInterpreter.o )
Linking a.out ...
/usr/bin/ld: /usr/lib/haskell-packages/ghc/lib/hint-0.3.3.2/ghc-7.0.3/libHShint-0.3.3.2.a(Interpreter.o): relocation R_X86_64_32S against `.data' can not be used when making a shared object; recompile with -fPIC
/usr/lib/haskell-packages/ghc/lib/hint-0.3.3.2/ghc-7.0.3/libHShint-0.3.3.2.a: could not read symbols: Bad value
collect2: ld gab 1 als Ende-Status zurück
So I added the -dynamic keyword, but that also doesn't work:
$ ghc -dynamic -shared -fPIC FFIInterpreter.hs librarymain.cpp -lstdc++
FFIInterpreter.hs:3:8:
Could not find module `Language.Haskell.Interpreter':
Perhaps you haven't installed the "dyn" libraries for package `hint-0.3.3.2'?
Use -v to see a list of the files searched for.
I searched my system for Interpreter.dyn_hi but didn't find it. Is there a way to get it?
I also tried to install hint manually, but this also doesn't deliver the Interpreter.dyn_hi file.
You have to install the library (and all it depends on) with the --enable-shared flag (using cabal-install) to get the .dyn_hi and .dyn_o files. You may consider setting that option in your ~/.cabal/config file.
Perhaps the easiest way is to uncomment the shared: XXX line in ~/.cabal/config, set the option to True and
cabal install --reinstall world
For safety, run that with the --dry-run option first to detect problems early. If the --dry-run output looks reasonable, go ahead and reinstall - it will take a while, though.

Error: Unbound module ... in Ocaml

I have just installed a library called Apron, the installation seems to be done:
#ubuntu$ find -name "*apron*"
./lib/libapron_debug.so
./lib/libapron.a
./lib/libapron.so
./lib/libapron_debug.a
./local/lib/ocaml/3.11.2/stublibs/dllapron_caml.so.owner
./local/lib/ocaml/3.11.2/stublibs/dllapron_caml.so
./local/lib/ocaml/3.11.2/apron
./local/lib/ocaml/3.11.2/apron/libapron_caml_debug.a
./local/lib/ocaml/3.11.2/apron/apron.cmxa
./local/lib/ocaml/3.11.2/apron/libapron_caml.a
./local/lib/ocaml/3.11.2/apron/apron.cmi
./local/lib/ocaml/3.11.2/apron/apron.cmx
./local/lib/ocaml/3.11.2/apron/apron.a
./local/lib/ocaml/3.11.2/apron/apron.cma
And I tried a first example:
(* with default setting:
apronppltop -I $MLGMPIDL_INSTALL/lib -I $APRON_INSTALL/lib
#load "gmp.cma";;
#load "apron.cma";;
#load "box.cma";;
#load "oct.cma";;
#load "polka.cma";;
#load "ppl.cma";;
#load "polkaGrid.cma";;
#install_printer Apron.Linexpr1.print;;
#install_printer Apron.Texpr1.print;;
#install_printer Apron.Lincons1.print;;
#install_printer Apron.Generator1.print;;
#install_printer Apron.Abstract1.print;;
let environment_print fmt x = Apron.Environment.print fmt x;;
let lincons1_array_print fmt x = Apron.Lincons1.array_print fmt x;;
let generator1_array_print fmt x = Apron.Generator1.array_print fmt x;;
#install_printer Apron.Var.print;;
#install_printer environment_print;;
#install_printer lincons1_array_print;;
#install_printer generator1_array_print;; *)
open Apron;;
...
However ocaml -c file.ml gives me Error: Unbound module Apron which happens on open Apron;;
Does anyone know why I could not load the Apron module? Thank you very much!
I should indicate the path of the Apron library with '-I' options. As it is installed in the standard library of OCaml, you only need to compile with:
ocamlc -I +apron -c file.ml