#!/usr/local/bin/perl
#
# This is a perl script to translate standard STL calls into
#  macro calls.  Also add necessary "fwd_*.h" include files.
#
# This is a first pass filter.  Assumes the containers have only
#  first argument speicified (if more are specified, you will need
#  to add one or more suffixes by hand).
#
# Outputs to new file prefixed with "STL_".  Also lists changes on
# stdout -- you may want to direct this to a file.
#
# Note: assumes no whitespace next to (inside) template delimiters:
#  e.g., vector <int> is OK, but not vector < int > or vector <const int>
#  in input. (Alternative has other problems.)
#
# ONLY MAKES ONE SUBSTITUTION PER LINE! (need second pass?)
#  May be a problem for container adapters.
#
# John Bartelt   20-Feb-1998
#

open(READFL, $ARGV[0]) ||
    die "Cannot open $ARGV[0].  usage: macroize.pl <filename> \n";


($infile) = $ARGV[0];
chomp $infile;
$outfile = 'STL_'.$infile;

open(READFL, "$infile");
print ("\n reading ", $infile, "\n");
open(WRITEFL, ">$outfile");
print (" writing ", $outfile, "\n\n");
while(<READFL>){
    ($inline) = $_;

#First, handle "sequence" (vector, deque, list) containers:
#
#look for <vector> include file, add <fwd_vector.h>
    if($inline =~ /#\s*include\s*<\s*vector\s*>.*/) {
	$outline = "#include <STLUtility/fwd_vector.h>\n" . $inline;
	print ("in: \n", $inline, "\n", "out: \n", $outline, "\n\n");

#look for <vector.h> include file, replace with <vector> and <fwd_vector.h>
    } elsif($inline =~ /#\s*include\s*<\s*vector.h\s*>.*/) {
	$outline = "#include <STLUtility/fwd_vector.h>\n#include <vector>\n";
	print ("in: \n", $inline, "\n", "out: \n", $outline, "\n\n");

#look for a vector template with no allocator specified:
    } elsif($inline =~ /(.*)(vector)(\s*)(<)(\S*)(>)(.*)/) {
	$outline = $1 . 'STL_VECTOR' . $3 . '('. $5 .')' .$7."\n";
	print ("in: \n", $inline, "\n", "out: \n", $outline, "\n\n");


#
#look for <deque> include file, add <fwd_deque.h>
    } elsif($inline =~ /#\s*include\s*<\s*deque\s*>.*/) {
       	$outline = "#include <STLUtility/fwd_deque.h>\n" . $inline;
	print ("in: \n", $inline, "\n", "out: \n", $outline, "\n\n");

#look for <deque.h> include file, replace with <deque> and <fwd_deque.h>
    } elsif($inline =~ /#\s*include\s*<\s*deque.h\s*>.*/) {
	$outline = "#include <STLUtility/fwd_deque.h>\n#include <deque>\n";
	print ("in: \n", $inline, "\n", "out: \n", $outline, "\n\n");

#look for a deque template with no allocator specified:
    } elsif($inline =~ /(.*)(deque)(\s*)(<)(\S*)(>)(.*)/) {
	$outline = $1 . 'STL_DEQUE' . $3 . '(' . $5 . ')' .$7."\n";
	print ("in: \n", $inline, "\n", "out: \n", $outline, "\n\n");

#
#look for <list> include file, add <fwd_list.h>
    } elsif($inline =~ /#\s*include\s*<\s*list\s*>.*/) {
	$outline = "#include <STLUtility/fwd_list.h>\n" . $inline;
	print ("in: \n", $inline, "\n", "out: \n", $outline, "\n\n");

#look for <list.h> include file, replace with <list> and <fwd_list.h>
    } elsif($inline =~ /#\s*include\s*<\s*list.h\s*>.*/) {
	$outline = "#include <STLUtility/fwd_list.h>\n#include <list>\n";
	print ("in: \n", $inline, "\n", "out: \n", $outline, "\n\n");

#look for a list template with no allocator specified:
    } elsif($inline =~ /(.*)(list)(\s*)(<)(.*)(>)(.*)/) {
	$outline = $1 . 'STL_LIST' . $3 . '(' . $5 . ')' .$7."\n";
	print ("in: \n", $inline, "\n", "out: \n", $outline, "\n\n");

#Now do associative containers (maps and sets)
#  Caution:  For templates, do multimap before map, multiset before set
#look for <map> include file, add <fwd_map.h>; for maps and multimaps 
    } elsif($inline =~ /#\s*include\s*<\s*map\s*>.*/) {
	$outline = "#include <STLUtility/fwd_map.h>\n" . $inline;
	print ("in: \n", $inline, "\n", "out: \n", $outline, "\n\n");

#look for <map.h> include file, replace with <map> and <fwd_map.h>
    } elsif($inline =~ /#\s*include\s*<\s*map.h\s*>.*/) {
	$outline = "#include <STLUtility/fwd_map.h>\n#include <map>\n";
	print ("in: \n", $inline, "\n", "out: \n", $outline, "\n\n");

#look for <multimap.h> (nonstandard) include file, replace with <map> and 
#                                                       <fwd_map.h>
    } elsif($inline =~ /#\s*include\s*<\s*multimap.h\s*>.*/) {
	$outline = "#include <STLUtility/fwd_map.h>\n#include <map>\n";
	print ("in: \n", $inline, "\n", "out: \n", $outline, "\n\n");

#	
#look for a multimap template with no comparison nor allocator specified:
    } elsif($inline =~ /(.*)(multimap)(\s*)(<)(.*)(>)(.*)/) {
	$outline = $1 . 'STL_MULTIMAP' . $3 . '(' . $5 . ')' .$7."\n";
	print ("in: \n", $inline, "\n", "out: \n", $outline, "\n\n");

#look for a map template with no comparison nor allocator specified:
    } elsif($inline =~ /(.*)(\s+map)(\s*)(<)(.*)(>)(.*)/) {
        $outline = $1 . ' STL_MAP' . $3 . '(' . $5 . ')' .$7."\n";
	print ("in: \n", $inline, "\n", "out: \n", $outline, "\n\n");

#
#look for <set> include file, add <fwd_set.h> ! 
    } elsif($inline =~ /#\s*include\s*<\s*set\s*>.*/) {
        $outline = "#include <STLUtility/fwd_set.h>\n" . $inline;
	print ("in: \n", $inline, "\n", "out: \n", $outline, "\n\n");

#look for <set.h> include file, replace with <set> and <fwd_set.h>
    } elsif($inline =~ /#\s*include\s*<\s*set.h\s*>.*/) {
        $outline = "#include <STLUtility/fwd_set.h>\n#include <set>\n";
	print ("in: \n", $inline, "\n", "out: \n", $outline, "\n\n");

#look for <multiset.h> (nonstandard) include file, replace with <set> and 
#                                                        <fwd_set.h>
    } elsif($inline =~ /#\s*include\s*<\s*multiset.h\s*>.*/) {
        $outline = "#include <STLUtility/fwd_set.h>\n#include <set>\n";
	print ("in: \n", $inline, "\n", "out: \n", $outline, "\n\n");

#look for a multiset template with no comparison nor allocator specified:
    } elsif($inline =~ /(.*)(multiset)(\s*)(<)(.*)(>)(.*)/) {
        $outline = $1 . 'STL_MULTISET' . $3 . '(' . $5 . ')' .$7."\n";
	print ("in: \n", $inline, "\n", "out: \n", $outline, "\n\n");

#look for a set template with no comparison nor allocator specified:
    } elsif($inline =~ /(.*)(set)(\s*)(<)(.*)(>)(.*)/) {
        $outline = $1 . 'STL_SET' . $3 . '(' . $5 . ')' .$7."\n";
	print ("in: \n", $inline, "\n", "out: \n", $outline, "\n\n");

#
# Finally, try the container adapters:  stack, queue, priority_queue
#  Only limited cases implemented here for now.
#
#look for <stack> include file, add <fwd_stack.h>
    } elsif($inline =~ /#\s*include\s*<\s*stack\s*>.*/) {
	$outline = "#include <STLUtility/fwd_stack.h>\n" . $inline;
	print ("in: \n", $inline, "\n", "out: \n", $outline, "\n\n");

#look for <stack.h> include file, replace with <stack>, <fwd_stack.h> and
#                                              <queue>, <fwd_queue.h>
    } elsif($inline =~ /#\s*include\s*<\s*stack.h\s*>.*/) {
	$outline = "#include <STLUtility/fwd_stack.h>\n#include <stack>\n#include <fwd_queue.h>\n#include <queue>\n";
	print ("in: \n", $inline, "\n", "out: \n", $outline, "\n\n");
        print ("INFO: fwd_queue.h and queue added to file $outfile.\nINFO:  May not be needed.");


#look for a stack template with no container or allocator specified:
    } elsif($inline =~ /(.*)(stack)(\s*)(<)(.*)(>)(.*)/) {
        $outline = $1 . 'STL_STACK' . $3 . '(' . $5 . ')' .$7."\n";
	print ("in: \n", $inline, "\n", "out: \n", $outline, "\n\n");

#
#look for <queue> include file, add <fwd_queue.h> 
    } elsif($inline =~ /#\s*include\s*<\s*queue\s*>.*/) {
        $outline = "#include <STLUtility/fwd_queue.h>\n" . $inline;
	print ("in: \n", $inline, "\n", "out: \n", $outline, "\n\n");

#look for <queue.h> include file, replace with <queue> and <fwd_queue.h>
    } elsif($inline =~ /#\s*include\s*<\s*queue.h\s*>.*/) {
        $outline = "#include <STLUtility/fwd_queue.h>\n#include <queue>\n";
	print ("in: \n", $inline, "\n", "out: \n", $outline, "\n\n");

#look for a priority_queue template with no container, comparison, or
#                                                    allocator specified:
    } elsif($inline =~ /(.*)(priority_queue)(\s*)(<)(.*)(>)(.*)/) {
        $outline = $1 . 'STL_PRIORITY_QUEUE' . $3 . '('. $5 .')' .$7."\n";
	print ("in: \n", $inline, "\n", "out: \n", $outline, "\n\n");

#look for a queue template with no container or allocator specified:
    } elsif($inline =~ /(.*)(queue)(\s*)(<)(.*)(>)(.*)/) {
        $outline = $1 . 'STL_QUEUE' . $3 . '(' . $5 . ')' .$7."\n";
	print ("in: \n", $inline, "\n", "out: \n", $outline, "\n\n");


#look for <priority_queue.h> (nonstandard) include file, replace with <queue> 
#                                                       and <fwd_queue.h>
    } elsif($inline =~ /#\s*include\s*<\s*priority_queue.h\s*>.*/) {
        $outline = "#include <STLUtility/fwd_queue.h>\n#include <queue>\n";
	print ("in: \n", $inline, "\n", "out: \n", $outline, "\n\n");

# else, just write the line as is:

    } else {
	$outline = $inline;
    }
    print WRITEFL ($outline);
}
close(READFL);
close(WRITEFL);



