#!/usr/bin/perl5 -w

### Name: c2js

### Author: Douglas Sweetser
### sweetser@TheWorld.com

### program description
my $help_string = <<HELP;

usage: c2c [-help] program.c(s)

creates file Qlib.mini.c

HELP
 

### algorithm
#   reads in files sequentially
#   does not write unused library functions


### modules
use strict;
use English;
use Getopt::Long;
    $Getopt::Long::autoabbrev = 1;   # use 1 letter
    $Getopt::Long::ignorecase = 0;   # be case sensitive please


### variables
my($program, @programs);           # The code, array of the code
   $program = "";
my($function_name, $function_flag);
   $function_flag = 1;
my($function, @functions, %functions);  # used in the code 
my($library);       # missing from javascript
   $library = "";
my($lib);                               # small library
my($file_in, $file_out);
my($help_flag);


### prototypes
sub _get_data ();           # command line processing
sub mini_library ($$);      # returns only library functions used
sub _get_functions ($$);    # gets functions based on XML tags

### main
# get data from command line
_get_data();


# Translate from c to javascript library, programs
$file_in = "Qlib.c";
open(FILE_IN, $file_in) || die ("could not open $file_in: $!");
while(<FILE_IN>) {
    $library .= $_;
}
close(FILE_IN);


# go through each program
for my $file (@ARGV) {

    my $temp = "";
    
    # add each line
    open(FILE_IN, $file) || die ("could not open $file: $!");
    while(<FILE_IN>) {
        $temp .= $_;

    }
    close(FILE_IN);

    $program .= $temp;    
}

# TESTING:{print "$program is: $program\n"};

# make a unique list of all functions used
(@functions) = $program =~ /(\w*)\(/gm;

foreach $function (@functions) {
    $functions{$function} = "";
}


# open file for output
$file_out = "Qlib.mini.c";
open(FILE_OUT, ">$file_out");

$lib = mini_library($library, \%functions);
print FILE_OUT $lib;

close(FILE_OUT);


### signals
exit(0);


### subroutines

# Get data from the command line
#
sub _get_data () {
    GetOptions("help" => \$help_flag);

    # print the help message
    if ($help_flag) {
        print ("$help_string");
        exit(0);
    }
}


# Given:
#   a library as a string
#   a pointer to a hash of used functions
# Returns a string of only those functions used
# NOTE: requires XML tags
#
sub mini_library ($$) {

    ### algorithm
    #   calls _get_functions with same arguments
    #   determines unique internal functions
    #   calls _get_functions again

    ### variables
    my ($input); 
    my ($func, @funcs, %functions_used, %functions_internal);
    my $result = "";
    my ($temp);

    # assign
    $input = $_[0];
    %functions_used = %{$_[1]};

    # include functions in the program to the result
    $result .= _get_functions ($input, \%functions_used) . "\n";

    # add internally used library functions
    # trying to avoid function foo by look for 
    # (function(,    function(, = function( and , function( 
    @funcs =   $input =~ /\((\w{2,})\(/gm;
    push @funcs,  $result =~ /^\s+(\w{2,})\(/gm;
    push @funcs,  $result =~ /\=\s+(\w{2,})\(/gm;
    push @funcs,  $result =~ /\,\s+(\w{2,})\(/gm;

    # find unique internal functions
    foreach $func (@funcs) {
        $functions_internal{$func} = "" unless (exists $functions_used{$func});
    }

    # include internal functions in the library to the result
    $result .= _get_functions ($input, \%functions_internal) . "\n";

    # return a string of code
    return $result;
}


# Given:
#   a library as a string
#   a pointer to a hash of used functions
# Returns a string of only those functions used
# NOTE: requires XML tags
#
sub _get_functions ($$) {

    ### algorithm
    #   loops through code one line at a time
    #   sets flag based on XML tag
    #   adds function if in hash passed in

    ### variables
    my($input, $library_line, @library_lines);
    my(%functions_used);
    my $result = "";

    # assign
    $input = $_[0];
    %functions_used = %{$_[1]};

    # go through lines 1 by 1
    @library_lines = split("\n", $input);
    foreach $library_line (@library_lines) {
            
        # get the function name from XML tag
        ($function_name) = $library_line =~ /function name=\"(\w*)\"/;

        # set a flag if it exists
        $function_flag = 1 if ($function_name and exists($functions_used{$function_name}));
        $function_name = "";

        #print
        $result .= $library_line . "\n" if($function_flag); 

        #reset
        if ($library_line =~ /<\/function/) {
            $function_flag = 0;
            $result .= "\n";
        }
    }

    # return a string of functions
    return $result;
}


### perldoc
=pod

=head1 NAME

c2c - produces Qlib.mini.c, a smaller lib

=head1 SYNOPSIS

B<c2c> [-help] programs.c(s)

=head1 DESCRIPTION

Tosses out unused functions

=head1 OPTIONS

=item I<-help>

usage: c2c [-help] program.c(s)

creates file Qlib.mini.c

=head1 AUTHOR

Doug Sweetser, sweetser@TheWorld.com

=head1 LICENSE

GPL - GNU General Public License, version 2

=cut






