#!/usr/bin/env perl

use warnings "all";

# Simple preprocessor to fix @ASM directives in z.mlp and z.mlip, and
# generate z.ml and z.mli

# This file is part of the Zarith library
# http://forge.ocamlcore.org/projects/zarith .
# It is distributed under LGPL 2 licensing, with static linking exception.
# See the LICENSE file included in the distribution.
#
# Copyright (c) 2010-2011 Antoine Miné, Abstraction project.
# Abstraction is part of the LIENS (Laboratoire d'Informatique de l'ENS),
# a joint laboratory by:
# CNRS (Centre national de la recherche scientifique, France),
# ENS (École normale supérieure, Paris, France),
# INRIA Rocquencourt (Institut national de recherche en informatique, France).


die "Usage: './z_pp.pl architecture'" unless $#ARGV==0;

# version, from META file

$v = `grep version META`;
($ver) = $v =~ /version\s*=\s*(\S+)/;

$ov = `ocamlc -version`;
($major,$minor,$extra) = split(/\./, $ov, 3);
if ($major > 4 || ($major == 4 && $minor >= 3)) {
    $noalloc = "[\@\@noalloc]";
} else {
    $noalloc = "\"noalloc\"";
}

# scan assembly

$ASM = "caml_z_${ARGV[0]}.S";
if (-e $ASM) {
    print "found assembly file $ASM\n";
    open F, "<$ASM";
    while (defined($l = <F>)) {
        if ($l =~ /^\s*PROLOG\s*\(\s*([A-Za-z0-9_]+)/) {
            $ASM_FUNS{$1} = 1;
        }
    }
    close F;
}

for $i (sort (keys %ASM_FUNS)) {
    print "  found $i\n";
}


# specialize .ml & .mli files

sub doml {
    $SUF = shift @_;
    open I, "<z.${SUF}p";
    open O, ">z.${SUF}";
    print O "(* This file was automatically generated by z_pp.pl from z.${SUF}p *)  ";
    while (defined($l = <I>)) {
        while ($l =~ /([A-Za-z0-9_]+)\@ASM/) {
            $f = $1;
            if (defined($ASM_FUNS{$f})) {
               $r = "\"ml_z_$f\" \"ml_as_z_$f\"";
            }
            else {
                $r = "\"ml_z_$f\"";
            }
            $l =~ s/$f\@ASM/$r/g;
        }
        $l =~ s/\@VERSION/$ver/;
        $l =~ s/\@NOALLOC/$noalloc/;
        print O "$l";
    }
    close F;
}

doml "ml";
doml "mli";

# generate a features.h file recording the functions defined in asm

open F, "> z_features.h";
for $i (sort (keys %ASM_FUNS)) {
    print F "#define Z_ASM_$i\n";
}
close F;
