PortSystem          1.0
PortGroup ocaml 1.0

name                ocaml-dypgen
version             20120619-1
revision            6
categories          lang devel ocaml
license             CeCILL-B
maintainers         nomaintainer
description         Self-extensible parsers and lexers for the Objective Caml programming language.
long_description    ${description}
homepage            http://dypgen.free.fr/
master_sites        ${homepage}

distname            dypgen-${version}
use_bzip2           yes

checksums           rmd160  c5e9bd52d964c0cd2a68780d40f28735700bb747 \
                    sha256  ecb53d6e469e9ec4d57ee6323ff498d45b78883ae13618492488e7c5151fdd97

depends_lib         port:ocaml-findlib \
                    port:ocaml

worksrcdir          dypgen

patchfiles          patch-Makefile.diff patch-dyplib-Makefile.diff \
                    patch-ocaml5.diff

configure {
    reinplace "s|@ocamlfind@|${ocamlfind_wrapper}|g" ${worksrcpath}/dyplib/Makefile
    # OCaml 5: bytes.[i] indexing syntax was removed; use Bytes.get instead
    reinplace {s|lexbuf\.lex_buffer\.\[p\]|(Bytes.get lexbuf.lex_buffer p)|g} \
        ${worksrcpath}/dyplib/dyplex.ml
    reinplace {s|String\.length lexbuf\.lex_buffer|Bytes.length lexbuf.lex_buffer|g} \
        ${worksrcpath}/dyplib/dyplex.ml
    # dyp.ml: lex_buffer is bytes; String.sub -> Bytes.sub_string, %s -> Bytes.to_string
    reinplace {s|String\.sub lexbuf\.lb_lexbuf\.lex_buffer|Bytes.sub_string lexbuf.lb_lexbuf.lex_buffer|g} \
        ${worksrcpath}/dyplib/dyp.ml
    reinplace {s|"1; %s\\n" lexbuf\.lb_lexbuf\.lex_buffer|"1; %s\n" (Bytes.to_string lexbuf.lb_lexbuf.lex_buffer)|g} \
        ${worksrcpath}/dyplib/dyp.ml
    # dyp.mli: Lexing.from_function uses bytes in OCaml 5, not string
    reinplace {s|(string -> int -> int) ->|(bytes -> int -> int) ->|} \
        ${worksrcpath}/dyplib/dyp.mli
    # OCaml 5 removed gprof support (-p flag); drop the prof build target
    reinplace {s|^all: dyp opt prof$|all: dyp opt|} \
        ${worksrcpath}/dyplib/Makefile
    # extract_type.mll: string mutation removed in OCaml 5; rebuild immutably
    reinplace {s|s\.\[len2-1\] <- r\.\[len-1\];|let s = String.sub s 0 (len2-1) ^ String.make 1 r.[len-1] in|} \
        ${worksrcpath}/dypgen/extract_type.mll
    # extract_type.mll: OCaml 5 dropped Pervasives, String.copy and String.fill,
    # and forbids in-place string mutation; switch to Stdlib/Bytes
    reinplace {s|Pervasives\.compare|Stdlib.compare|} ${worksrcpath}/dypgen/extract_type.mll
    reinplace {s|String\.copy (Buffer\.contents string_buf)|(Buffer.contents string_buf)|g} \
        ${worksrcpath}/dypgen/extract_type.mll
    reinplace {s|fix_variant s lexbuf2;|let s = Bytes.of_string s in fix_variant s lexbuf2; let s = Bytes.to_string s in|g} \
        ${worksrcpath}/dypgen/extract_type.mll
    reinplace {s|fun_typ\.\[i\] <- ' '; fun_typ\.\[i+2\] <- ' ';|Bytes.set fun_typ i ' '; Bytes.set fun_typ (i+2) ' ';|} \
        ${worksrcpath}/dypgen/extract_type.mll
    reinplace {s|fun_typ\.\[i+1\] <- ' ';|Bytes.set fun_typ (i+1) ' ';|} \
        ${worksrcpath}/dypgen/extract_type.mll
    reinplace {s|String\.fill fun_typ|Bytes.fill fun_typ|} ${worksrcpath}/dypgen/extract_type.mll
    # dypgen_lexer.mll: build a single-char string immutably
    reinplace {s|let string_of_char c = let x = " " in x\.\[0\] <- c; x|let string_of_char c = String.make 1 c|} \
        ${worksrcpath}/dypgen/dypgen_lexer.mll
    # insert_linenum.mll: the line-number buffer is a mutable byte sequence now
    reinplace {s|let buffer = ref ""|let buffer = ref Bytes.empty|} ${worksrcpath}/dypgen/insert_linenum.mll
    reinplace {s|let space = String\.make 20 ' '|let space = Bytes.make 20 ' '|} \
        ${worksrcpath}/dypgen/insert_linenum.mll
    reinplace {s|String\.blit str 0 space 0 (String\.length str)|Bytes.blit_string str 0 space 0 (String.length str)|} \
        ${worksrcpath}/dypgen/insert_linenum.mll
    reinplace {s|String\.blit space 0 !buffer pos\.pos_cnum 20|Bytes.blit space 0 !buffer pos.pos_cnum 20|} \
        ${worksrcpath}/dypgen/insert_linenum.mll
    reinplace {s|let result = !buffer in buffer := ""; result|let result = !buffer in buffer := Bytes.empty; Bytes.to_string result|} \
        ${worksrcpath}/dypgen/insert_linenum.mll
    reinplace {s|String\.blit fn2 0 parser_code pos\.pos_cnum (len+8)|Bytes.blit_string fn2 0 parser_code pos.pos_cnum (len+8)|} \
        ${worksrcpath}/dypgen/insert_linenum.mll
    # dypgen.ml: feed Insert_linenum the bytes buffer it now expects
    reinplace {s|Insert_linenum\.buffer := String\.copy parser_code$|Insert_linenum.buffer := Bytes.of_string parser_code|} \
        ${worksrcpath}/dypgen/dypgen.ml
    reinplace {s|Insert_linenum\.buffer := String\.copy parser_code_mli;|Insert_linenum.buffer := Bytes.of_string parser_code_mli;|} \
        ${worksrcpath}/dypgen/dypgen.ml
    reinplace {s|(try Insert_linenum\.replace_filename parser_code input_file_short lexbuf|let parser_code = Bytes.of_string parser_code in (try Insert_linenum.replace_filename parser_code input_file_short lexbuf|} \
        ${worksrcpath}/dypgen/dypgen.ml
    reinplace {s|output_string dest_file parser_code;|output_string dest_file (Bytes.to_string parser_code);|} \
        ${worksrcpath}/dypgen/dypgen.ml
}

use_configure       no

use_parallel_build  no

build.target        dyp

destroot.args       BINDIR=${prefix}/bin MANDIR=${prefix}/share/man/man1

post-destroot {
    xinstall -m 755 -d ${destroot}${prefix}/share/examples \
        ${destroot}${prefix}/share/doc/${name}
    file copy ${worksrcpath}/demos ${destroot}${prefix}/share/examples/${name}
    xinstall -m 644 -W ${worksrcpath} dypgen-doc.pdf CHANGES \
        CREDITS INSTALL Licence_CeCILL-B_V1-en.txt Licence_CeCILL-B_V1-fr.txt \
        ${destroot}${prefix}/share/doc/${name}
}

livecheck.type      regex
livecheck.url       http://dypgen.free.fr/download.html
livecheck.regex     dypgen-(\[0-9.-\]+).tar.bz2
