#!/usr/bin/perl

##- Nanar <nanardon@mandrake.org>
##-
##- This program is free software; you can redistribute it and/or modify
##- it under the terms of the GNU General Public License as published by
##- the Free Software Foundation; either version 2, or (at your option)
##- any later version.
##-
##- This program is distributed in the hope that it will be useful,
##- but WITHOUT ANY WARRANTY; without even the implied warranty of
##- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
##- GNU General Public License for more details.
##-
##- You should have received a copy of the GNU General Public License
##- along with this program; if not, write to the Free Software
##- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# $Id: rpmh2tbl 73 2005-12-19 00:39:07Z nanardon $

use strict;
use warnings;

use Getopt::Long;

my @availlabletables;

# Binding we want
# In this file we'll found
# FILE.h => 
#   Constant matching the REGEXP goes in this table.
#   'REGEXP' => table,

my %file_const = (
    'rpmts.h' => {
        '^_?(RPMVSF_[\w_]+)' => 'rpmvsflags',
        '^(RPMTRANS_TYPE_[\w_]+)' => 'rpmtsType',
        '^(RPMTS_OP_[\w_]+)' => 'rpmtsOpX',
    },
    'rpmlib.h' => {
        '^(RPMDBI_[\w_]+)' => 'rpmdbi',
        '^_?(RPMSENSE_[\w_]+)' => 'rpmsenseflags',
        '^(RPMTAG_[\w_]+)' => 'rpmTag',
        '^(RPMRC_[\w_]+)' => 'rpmRC',
        '^(RPMFILE_[^(STATE_)][\w_]+)' => 'rpmfileAttrs',
        '^(RPMFILE_STATE_[\w_]+)' => 'rpmfileState',
        '^(RPM_MACHTABLE_[\w_]+)' => 'rpm_machtable',
        '^(RPMPROB_FILTER_[\w_]+)' => 'rpmprobFilterFlags',
        '^(FA_[\w_]+)' => 'fileAction',
        '^(PIPE|CDEV|XDIR|BDEV|REG|LINK|SOCK)$' => 'fileTypes',
        '^(RPMTRANS_FLAG_[\w_]+)' => 'rpmtransFlags',
        '^(INSTALL_[\w_]+)' => 'rpmInstallInterfaceFlags',
        '^(UNINSTALL_[\w_]+)' => 'rpmEraseInterfaceFlags',
        '^(RPMSIGTAG_[\w_]+)' => 'rpmtagSignature',
    },
    'rpmps.h' => {
        '^(RPMPROB_[\w_]+)' => 'rpmProblemType',
    },
    'rpmcli.h' => {
        '^(RPMSIGN_[\w_]+)' => 'rpmSignFlags',
        '^(VERIFY_[\w_]+)' => 'rpmVerifyFlags',
    },
    'rpmdb.h' => {
        '^(RPMMIRE_[\w_]+)' => 'rpmMireMode',
    },
    'header.h' => {
        '^(HEADER_MAGIC_[\w_]+)' => 'hMagic',
        '^(RPM_[\w]+)_TYPE$' => 'rpmTagType',
    },
    'rpmbuild.h' => {
        '^(RPMBUILD_[\w_]+)' => 'rpmBuildFlags',
        '^(PART_[\w_]+)' => 'rpmParseState',
    },
    'rpmerr.h' => {
        '^(RPMERR_[\w_]+)' => 'rpmerrCode',
    },
    'rpmmacro.h' => {
        '^(RMIL_[\w_]+)' => 'rpmMacrosContext',
    },
    'rpmte.h' => {
        '^(TR_[\w_]+)' => 'rpmElementType',
    },
    'rpmlog.h' => {
        '^(RPMLOG_(?!PRI$|MAKEPRI$|FAC$|MASK$|UPTO$)[\w_]+)' => 'rpmlog',
    },
    'rpmmessage.h' => {
        '^(RPMCALLBACK_[\w_]+)' => 'rpmCallbackType',
        '^(RPMMESS_[\w_]+)' => 'rpmmess',
    },
);

my %tableprefix = (
    rpmmess => 'RPMMESS_',
    rpmCallbackType => 'RPMCALLBACK_',
    rpmlog => 'RPMLOG_',
    rpmdbi => 'RPMDBI_',
    rpmElementType => 'TR_',
    rpmMacrosContext => 'RMIL_',
    rpmerrCode => 'RPMERR_',
    rpmParseState => 'PART_',
    rpmBuildFlags => 'RPMBUILD_',
    rpmTagType => 'RPM_',
    hMagic => '',
    rpmMireMode => 'RPMMIRE_',
    rpmsenseflags => 'RPMSENSE_',
    rpmtsTransFlag => 'RPMVSF_',
    rpmTag => 'RPMTAG_',
    rpmtsType => 'RPMTRANS_TYPE_',
    rpmtsOpX => 'RPMTS_OP_',
    rpmRC => 'RPMRC_',
    rpmfileState => 'RPMFILE_STATE_',
    rpmfileState => 'RPMFILE_',
    rpm_machtable => 'RPM_MACHTABLE_',
    rpmprobFilterFlags => 'RPMPROB_FILTER_',
    fileAction => 'FA_',
    fileTypes => '',
    rpmtransFlags => 'RPMTRANS_FLAG_',
    rpmInstallInterfaceFlags => 'INSTALL_',
    rpmEraseInterfaceFlags => 'UNINSTALL_',
    rpmtagSignature => 'RPMSIGTAG_',
    rpmProblemType => 'RPMPROB_',
    rpmSignFlags => 'RPMSIGN_',
    rpmVerifyFlags => 'VERIFY_',
    rpmvsflags => 'RPMVSF_',
);


my $ch = *STDOUT;

sub parseconst {
    my ($header) = @_;
    my ($hbasename) = $header =~ m#(?:.*/)(.*)$#;

    my $hconstant = $file_const{$hbasename} or return;
    open(my $hheader, "<", $header) or die "Can't open $header\n";

    my %constants_found;
    my $i;
    
    my $line = <$hheader>;
    $line =~ /^\s*#\s*ifndef\s+(\S+)/;
    my $headerdef = $1 if($1);
    
    while ($line = <$hheader>) {
        $line =~ s#^\s*/\*[^\*]*\*/##;
        my ($w, $c) = $line =~ m!(?:#\s*define\s*)?([\w_]+)[^(/\*)]*(/\*.*\*/)?!;
        defined($w) or next;
        foreach my $regexp (keys %{$hconstant}) {
            if ($w =~ /$regexp/) {
                $constants_found{$hconstant->{$regexp}}{$w}{n} ||= ++$i;
                $constants_found{$hconstant->{$regexp}}{$w}{c} ||= $c;
                $constants_found{$hconstant->{$regexp}}{$w}{s} ||= $1;
            }
        }
    }

    close($hheader);

    while (my ($tbl, $const) = each (%constants_found)) {
        $tableprefix{$tbl} ||= "";
        print $ch <<EOF;

/* From $hbasename
 * prefix tag: $tableprefix{$tbl}
 * table: $tbl */
EOF
        printf $ch "static const struct rpmconstant_s %sctbl[] = {\n",
            $tbl;
        print $ch "#ifdef $headerdef\n" if ($headerdef);
        foreach my $c (sort { $const->{$a}{n} <=> $const->{$b}{n} } keys %$const) {
            printf $ch "\t{ \"%s\", %s }, %s\n",
                uc($const->{$c}{s} || $c), $c, $const->{$c}{c} || "";
        }
        print $ch "#endif /* $headerdef */\n" if ($headerdef);
        printf $ch "\t{ %s, %s } /* NULL terminated (%s) */\n", "NULL", "0", $tbl;
        print $ch "};\n";
        printf $ch "const struct rpmconstant_s * %sctable = %sctbl;\n\n", $tbl, $tbl;

        push @availlabletables, $tbl;
    }
}

printf $ch <<EOF
/* File automatically generate by $0
 * Olivier Thauvin <thauvin at aerov.jussieu.fr>
 * Parsed files:
 * %s
 */

#define RPMCONSTANT_INTERNAL
#include "rpmconstant.h"
 
EOF
, join("\n * ", @ARGV);

GetOptions(
);

foreach (@ARGV) {
    parseconst($_);
}

print $ch "static const struct rpmconstantlist_s rpmconstanttp[] = {\n";
foreach (sort(@availlabletables)) {
    printf $ch "\t{ %s, %s, %s },\n", 
        '(void *)'.$_."ctbl",
        '"' . lc($_) . '"',
        $tableprefix{$_} ? "\"$tableprefix{$_}\"" : "NULL";
}
printf $ch "\t{ %s, %s, %s } /* NULL terminated */\n", "(void *) NULL", "NULL", "NULL";
print $ch "};\n";
printf $ch "const struct rpmconstantlist_s * rpmconstanttype = rpmconstanttp;\n";
print $ch "const int rpmconstanttypesize = sizeof(rpmconstanttp) / sizeof(rpmconstanttp[0]) -1;\n";

