#!/usr/bin/perl

=begin metadata

Name: xargs
Description: construct argument list(s) and execute utility
Author: Gurusamy Sarathy, gsar@umich.edu
License:

=end metadata

=cut

#
# An xargs clone.
#
# Gurusamy Sarathy <gsar@umich.edu>
#

use File::Basename qw(basename);
use Getopt::Std;
use Text::ParseWords;

use constant EX_SUCCESS => 0;
use constant EX_FAILURE => 1;

my $Program = basename($0);

my %o;
getopts('tn:l:s:I:', \%o) or die <<USAGE;
Usage:
	$Program [-t] [-n num] [-l num] [-s size] [-I repl] prog [args]

	-t	trace execution (prints commands to STDERR)
	-n num	pass at most 'num' arguments in each invocation of 'prog'
	-l num	pass at most 'num' lines of STDIN as 'args' in each invocation
	-s size	pass 'args' amounting at most to 'size' bytes in each invocation
	-I repl	for each line in STDIN, replace all 'repl' strings in 'args'
		  before execution
USAGE

for my $opt (qw( l n s )) {
    next unless (defined $o{$opt});
    if (!length($o{$opt}) || $o{$opt} =~ m/\D/) {
	warn "$Program: option $opt: invalid number '$o{$opt}'\n";
	exit EX_FAILURE;
    }
    if ($o{$opt} == 0) {
	warn "$Program: option $opt: number must be > 0\n";
	exit EX_FAILURE;
    }
}

my @args = ();

$o{I} ||= '{}' if exists $o{I};
$o{l} = 1 if $o{I};

while (1) {
    my $line = "";
    my $totlines = 0;
    while (<STDIN>) {
	chomp;
	$line .= $_ if $o{I};
	$totlines++;
	push @args, grep defined, quotewords('\s+', 1, $_);
	last if $o{n} and @args >= $o{n};
	last if $o{s} and length("@args") >= $o{s};
	last if $o{l} and $totlines >= $o{l};
    }
    my @run = @ARGV;
    push @run, 'echo' unless (@run);
    if ($o{I}) {
	exit(EX_SUCCESS) unless length $line;
	for (@run) { s/\Q$o{I}\E/$line/g; }
    }
    elsif ($o{n}) {
	exit(EX_SUCCESS) unless @args;
	push @run, splice(@args, 0, $o{n});
    }
    else {
	exit(EX_SUCCESS) unless @args;
	push @run, @args;
	@args = ();
    }
    if ($o{t}) { local $" = "', '"; warn "exec '@run'\n"; }
    if (system(@run) != 0) {
	warn "$0: $run[0]: $!\n";
	exit($? >> 8);
    }
}

=encoding utf8

=head1 NAME

xargs - construct argument list(s) and execute utility
