#!/usr/bin/perl

use v5.36;
use autodie;
use warnings;

use File::Basename qw(dirname);
use File::Spec();
use Getopt::Long;

my $opt_includes = 1;

GetOptions(
    'includes!' => \$opt_includes,
) or exit 1;

if (@ARGV) {
    dump_file($_) for @ARGV;
}
else {
    dump_handle(\*STDIN);
}

my %file_seen;
my $current_file;

sub dump_file {
    my $file = shift;

    if ($file_seen{$file}++) {
        print "# file '$file' already seen\n";
        return;
    }

    my $save_current_file = $current_file;
    $current_file = $file;
    open my $fh, '<', $file;
    print "# $file start\n";
    dump_handle($fh);
    print "# $file end\n";

    $current_file = $save_current_file;
}

sub dump_handle {
    my $fh      = shift;
    my $line_no = 0;
    while (defined(my $line = <$fh>)) {
        $line_no++;

        if ($opt_includes and $line =~ /^\s*include\s+(.+?)\s*$/) {
            my $new_file = $1;
            if (File::Spec->file_name_is_absolute($new_file)) {
                my @matches = glob($new_file);
                die "line $line_no: no matches for '$new_file'\n" unless @matches;
                dump_file($_) for @matches;
            }
            else {
                die
"line $line_no: can't include a relative file name when processing a stream\n"
                  unless $current_file;

                my @matches =
                  glob File::Spec->catfile(dirname($current_file), $new_file);
                die "line $line_no: no matches for '$new_file'\n" unless @matches;
                dump_file($_) for @matches;
            }
        }
        else {
            print $line;
        }
    }
}
