use warnings;
use strict;
my $skipnext = 0;
my $current_acct = 0;
my $where = 0;
my $credit = 0;
my $now = `date +%C%y%m%d%H%M`;
chomp $now;
my $account_dir = `echo \$HOME`;
chomp $account_dir;
$account_dir = $account_dir . ;
switch_acct ();
update_future ();
if ( -1 == $#ARGV ) {
print ;
print .
;
exit ();
}
main ();
=pod
sub main: process our arguments, and also drive execution
=cut
sub main {
foreach (@ARGV) {
if ($skipnext) { $where++; $skipnext--; next; }
elsif ($_ eq or $_ eq ) {
usage ();
}
elsif ($_ eq or $_ eq ) {
version ();
}
elsif ($_ eq or $_ eq ) {
if (my $out = getName ())
{
print account$current_acct$out;
}
else
{
print $current_acct;
}
}
elsif (/^\-[0-9]+$/) {
$current_acct = -1 * $_;
if (-1 == switch_acct ())
{
print $current_acct;
usage ();
}
update_future ();
print $current_acct;
}
elsif ($_ eq or $_ eq ) {
print . sprintf (, balance ()) . ;;
}
elsif ($_ eq or $_ eq ) {
$credit = 1;
my $out = trans ();
my $bal = sprintf (, balance ());
if ( 0 == $out )
{
print $bal;
$skipnext = 2;
}
elsif ( -1 == $out )
{
print ;
usage ();
}
elsif ( -2 == $out )
{
print $ARGV$where;
}
else
{
print ;
}
}
elsif ($_ eq or $_ eq ) {
$credit = 0;
my $out = trans ();
my $bal = sprintf (, balance ());
if (0 == $out)
{
print $bal;
$skipnext = 2;
}
elsif (-1 == $out)
{
print ;
usage ();
}
elsif (-2 == $out)
{
print $ARGV$where;
}
else
{
print ;
}
}
elsif ($_ eq or $_ eq ) {
my $out = create ();
if (1 == $out)
{
print account$ARGV$where;
$skipnext = 2;
}
elsif (0 == $out)
{
print $ARGV$where;
}
elsif (-1 == $out)
{
print ;
usage ();
}
}
elsif ($_ eq or $_ eq ) {
my $out = futurebalance ();
if (-1 == $out)
{
print ;
usage ();
}
elsif (0 == $out)
{
print ;
}
else
{
$out = sprintf (, $out);
print account$current_acct$out;
$skipnext = 1;
}
}
elsif ($_ eq or $_ eq ) {
$credit = 1;
my $out = futuretrans ();
if (0 == $out)
{
$skipnext = 3;
}
elsif (-1 == $out)
{
print ;
usage ();
}
elsif (-2 == $out)
{
print $ARGV$where;
}
elsif (-3 == $out)
{
print *future;
print $now;
}
}
elsif ($_ eq or $_ eq ) {
$credit = 0;
my $out = futuretrans ();
if (0 == $out)
{
$skipnext = 3;
}
elsif (-1 == $out)
{
print ;
usage ();
}
elsif (-2 == $out)
{
print $ARGV$where;
}
elsif (-3 == $out)
{
print *future;
print $now;
}
}
else {
print $_;
usage ();
}
$where++;
}
}
=pod
sub usage: shows how to invoke the command-line program
=cut
sub usage {
my $exec = brinance;
print $execargs$exec$exec$execamountcomment$execamountcomment$execamountcomment$execamountcomment$execaction$exec$exec$exec$exec;
exit (0);
}
=pod
sub version: prints current version of command line program
=cut
sub version {
print ;
}
=pod
sub getName: returns the name of the current account, or undefined if there is no valid name
=cut
sub getName {
open (ACCOUNT, ($account_dir . account . $current_acct)) or die . $account_dir . account . $current_acct;
my $top = <ACCOUNT>;
my $title = undef;
if ($top =~ )
{
(undef, $title) = split(/: /, $top);
chomp $title;
}
close ACCOUNT;
return $title;
}
=pod
sub balance: returns the balance of the current account
=cut
sub balance {
open (ACCOUNT, ($account_dir . account . $current_acct)) or die . $account_dir . account . $current_acct;
my $total = 0;
for (<ACCOUNT>)
{
if (/^#/)
{
}
else
{
$total += $_;
}
}
close ACCOUNT;
return $total;
}
=pod
sub trans: applies a transaction to the current account, either credit or debit
return values:
0 - success
-1 - too few arguments (needs two)
-2 - zero value transaction, which could mean a non-number was specified as the transaction amount
=cut
sub trans {
open (ACCOUNT, ($account_dir . account . $current_acct)) or die . $account_dir . account . $current_acct;
if ( ($where+2) > $#ARGV )
{
return -1;
}
if ($credit)
{
$ARGV[$where+1] = 1 * $ARGV[$where+1];
}
else
{
$ARGV[$where+1] = -1 * $ARGV[$where+1];
}
if ( 0 == $ARGV[$where+1] )
{
return -2;
}
else
{
my $amount = $ARGV[$where+1];
my $comment = $ARGV[$where+2];
print ACCOUNT $now;
print ACCOUNT $comment;
print ACCOUNT $amount;
}
close ACCOUNT;
return 0;
}
=pod
sub create: create a new account
return values:
1 - success
0 - account already exists, no change
-1 - too few arguments, needs 2
=cut
sub create {
my $worked;
if ( ($where+2) > $#ARGV )
{
return -1;
}
my $acct_name = $ARGV[$where+1];
my $acct_num = $ARGV[$where+2];
if (-e ($account_dir . account . $acct_num))
{
$worked = 0;
}
else
{
open (ACCOUNT, ($account_dir . account . $acct_num)) or die ;
open (FUTURE, ($account_dir . future . $acct_num)) or die ;
print ACCOUNT $acct_name;
print FUTURE $acct_name;
close ACCOUNT;
close FUTURE;
$worked = 1;
}
return $worked;
}
=pod
sub futurebalance: determines balance at given future time
return values:
-1 - too few arguments, needs 1
else - the future balance
=cut
sub futurebalance {
if ( ($where+1) > $#ARGV )
{
return -1;
}
open (FUTURE, ($account_dir . future . $current_acct)) or return 0;
my $rdate;
if ($ARGV[$where+1] =~ /^\+\d*/)
{
my (undef, $plus_days) = split (/\+/, $ARGV[$where+1]);
$rdate = addDate ($now, $plus_days);
}
else
{
$rdate = $ARGV[$where+1];
}
my $total = balance ();
my $grabnext = 0;
while (<FUTURE>)
{
if (/^#\d{12}$/)
{
my (undef, $cdate) = split (/#/, $_);
chomp $cdate;
if ($cdate < $rdate)
{
$grabnext = 1;
}
}
elsif (/^#/)
{
}
elsif ($grabnext)
{
$total += $_;
$grabnext = 0;
}
}
close FUTURE;
return $total;
}
=pod
sub futuretrans: applies a transaction at specified future time
return values:
-1 - too few arguments, needs three
-2 - zero-value transaction
-3 - time specified is not in the future
=cut
sub futuretrans {
if ( ($where+3) > $#ARGV )
{
return -1;
}
if ($credit)
{
$ARGV[$where+2] = 1 * $ARGV[$where+2];
}
else
{
$ARGV[$where+2] = -1 * $ARGV[$where+2];
}
open (FUTURE, ($account_dir . future . $current_acct)) or die . $account_dir . future . $current_acct;
if ( 0 == $ARGV[$where+2] )
{
return -2;
}
else
{
my $date;
if ($ARGV[$where+1] =~ /^\+\d*/)
{
my (undef, $plus_days) = split (/\+/, $ARGV[$where+1]);
$date = addDate ($now, $plus_days);
}
else
{
$date = $ARGV[$where+1];
}
my $amount = $ARGV[$where+2];
my $comment = $ARGV[$where+3];
if ( $now >= $date )
{
return -3;
}
else
{
print FUTURE $date;
print FUTURE $comment;
print FUTURE $amount;
}
}
close FUTURE;
return 0;
}
=pod
sub update_future: called before working with an account to apply future transactions if they are now passed
=cut
sub update_future {
open (FUTURE, ($account_dir . future . $current_acct)) or die . $account_dir . future . $current_acct;
open (ACCOUNT, ($account_dir . account . $current_acct)) or die . $account_dir . account . $current_acct;
open (NEWFUTURE, ($account_dir . newfuture . $current_acct)) or die . $account_dir . newfuture . $current_acct;
my @futures = {};
my $futures_i = 0;
my $grab = 0;
my @nfutures = {};
my $nfutures_i = 0;
my $ngrab;
for (<FUTURE>)
{
chomp;
if ($grab)
{
$futures[$futures_i++] = $_;
$grab--;
next;
}
if ($ngrab)
{
$nfutures[$nfutures_i++] = $_;
$ngrab--;
next;
}
if (/^#\d{12}$/)
{
my (undef, $date) = split(/#/, $_);
if ($date <= $now)
{
$futures[$futures_i++] = $_;
$grab = 2;
}
else
{
$nfutures[$nfutures_i++] = $_;
$ngrab = 2;
}
}
elsif (/^#NAME: /)
{
$nfutures[$nfutures_i++] = $_;
}
}
for (my $i = 0; $i < $futures_i; $i++)
{
print ACCOUNT $futures$i;
}
for (my $i = 0; $i < $nfutures_i; $i++)
{
print NEWFUTURE $nfutures$i;
}
close ACCOUNT;
close FUTURE;
close NEWFUTURE;
my $src = ($account_dir . newfuture . $current_acct);
my $trg = ($account_dir . future . $current_acct);
system ($src$trg);
}
=pod
sub switch_acct: safety for switching account, give a failure if the account isnt auto-create any other account
-1 - account doesnt exist
{
if ( 0 == $current_acct )
{
open (ACCOUNT, ($account_dir . account0)) or die ;
open (FUTURE, ($account_dir . future0)) or die ;
print ACCOUNT ;
print FUTURE ;
close ACCOUNT;
close FUTURE;
return 0;
}
else
{
return -1;
}
}
else
{
return 1;
}
}
=pod
sub addDate: adds a second argument (number of days) to the first argument (a whole 12-digit date)
accounts for different length months and leap-year, but not leap-leap years (ie 2200)
=cut
sub addDate (){
my ($year, undef) = split (/........$/, $_[0]);
my (undef, $min) = split (/^..../, $_[0]);
my ($month, undef) = split (/......$/, $min);
(undef, $min) = split (/^../, $min);
my ($day, undef) = split (/....$/, $min);
(undef, $min) = split (/^../, $min);
my ($hour, undef) = split (/..$/, $min);
(undef, $min) = split (/^../, $min);
if ($min > 59) {
$min = 59;
}
if ($hour > 23) {
$hour = 23;
}
my %months = ( 1 => 31, 2 => 28, 3 => 31,
4 => 30, 5 => 31, 6 => 30,
7 => 31, 8 => 31, 9 => 30,
10 => 31, 11 => 30, 12 => 31 );
$day += ($_[1] * 1);
$month *= 1;
my $leap = 0;
while ($day > $months{$month}) {
if ( $month == 2 && (($year % 4) == 0)) {
if ( 29 == $day )
{
$leap = 1;
$day = 28;
}
else
{
$day -= 29;
$month++;
}
}
else {
$day -= $months{$month};
$month++;
}
while ($month > 12)
{
$month -= 12;
$year++;
}
}
if ($leap)
{
$day = 29;
}
while ($month > 12)
{
$month -= 12;
$year++;
}
if ($year > 9999)
{
$year = 9999;
}
$month *= 1; $day *= 1;
if ($month < 10) {
$month = . $month;
}
if ($day < 10) {
$day = . $day;
}
return $year . $month . $day . $hour . $min;
}
« Back to main Brinance page