#!/usr/bin/perl # # Copyright 2017 Peter Cherepanov # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # $fmt_sn0= "%d Snoopy Calendar XXXXXXXX\n"; $fmt_sn1a= "Also good for %d, %d%s%s"; $fmt_sn1b=" XXXXXXXXXXXX\n"; @fmt_sn2=( " XXXXXXXXXXXXXXXXXX\n" ," XXX XXXXXX XXXXXX\n" ," OOOO XXXXX OOOOOOO XXXXXX\n" ," OOOOO XX OOOOOOOOOO XXXXXXX\n" ," OOOOO XX OOOOOOOOOOO XXXXXXXXX\n" ," OOOOO XX OOOOOOOOOOO XXXXXXXXXX\n" ," OOOOO XX OOOOOOOOOOO X XXXXXXXXXXX\n" ," OOOO XX OOOOOOOO X XXXXXXXXXX\n" ," XXXXX X XXXX XXXX XXXXXXXXXXXX XXXXXXXXX\n" ," XXXXXXXXXXXX XXXX XXX XX XXX XXXXXXXXX XXXXXXXXXXX\n" ," XXX XX XXXX XXXX XXXXXXXXX XXXXXXX\n" ," XXX XXXXX XXXXX XXXXXXX XX XXXXXX\n" ," XXX XXXXX XXXXX XXXXX XXXXX XXXXX\n" ," XXX XXXX XXXX XXXXX XXXXXX XXXX\n" ," XXX XX XX XXX XXXXXXX XXXX\n" ," XXX XXX XXXXXXX XXXX\n" ," XXX XXXXXX XXX XXXXXXX XXXX\n" ," XXX XXXXXXXXXX XXX XXXXXX XXXXX\n" ," XXX XXXXXXXXXXX XXX XXXXX XXXXXX\n" ," XXX XXXXXXXXXX XXX XXX XXXXXXX\n" ," XXX XXXXXX XXXX XXXXXXX\n" ," XXX XX XXXXXXXXXXXXXXXXX\n" ," XXX XX XXXXXXXXXXXXXXX\n" ," XXX XX XXXXXXXXXXXXXX\n" ," XXX XX XXXXX XXXXXX\n" ," XXX XX XX XXXXXXXXXXXXX\n" ," XXX XX XX XXX XXXXXXX\n" ," XXXX X XXXXXXXXXXXXXXXXXXX XXX XXXXXXX\n" ," XXXXXXXXXXXXXXXXXXXXXXX XX XX XXX\n" ," XXX XXXX XXXXX\n" ," XXX XXXXXXXXX\n" ," XXX XXXXX\n" ," XXX XXXXXXXXXX\n" ," XXXXXXXXXXXXXX\n" ," XXXXXXXXXXXX\n" ," XX XX\n" ," XXXXXXXXXXXXXXXX X\n" ," XXXXXXXXXXXXXXXXX XXX X\n" ," XXX XX XXXX XX\n" ," XXX X X XXX X XXX\n" ," XX XX X XXX XXX\n" ," XX XXXXX XX XX XXXX\n" ," XX XXX XXX XX XX XXX X\n" ," XX X XX XX XXX X\n" ," XX X XXX XX X\n" ," XX X X X X\n" ," XX X XXX X X X\n" ," XX XXXXXXXXXXX XX X X X\n" ," XX XX XXX XX X XX X\n" ," XX XX XXX XX X XXX X\n" ," XX XX XXX XXOX X\n" ," XX XXOOX XX\n" ," XX XXOOOOX XXXXO O\n" ," XX XXOOOOX XXXXO O\n" ," XX XXOOOOOXXXXX O O O\n" ," XX XXO O O O O O O\n" ," XX XX O O O O O O\n" ," XX XX O O O O O\n" ," XXX XX O O O O\n" ," XXX XX O O O\n" ," XXXXXXXX X XX\n" ," XX X XX\n" ," XX X X\n" ," XX X XX\n" ," XX X XX XXXXXXX\n" ," XXXXXXXXXX XX XX XXXXX XXXXX\n" ," XXXXXX XXXX X XX XXX\n" ," XXXX X XX XX XX\n" ," XXX XX XX XX XX\n" ," XX XX XX XXXXXXX XXX XXX XX\n" ," XX XXX XXX XXXXX XXXXXXXXXXXXXXXXXXXX\n" ," XXXXXXXXXXXXXXXXXXXXXXXXX\n\n\n"); $fmt_year= " %d\n\n"; $week_line= " S M Tu W Th F S S M Tu W Th F S S M Tu W Th F S\n"; $month_line0= " Jan Feb Mar\n"; $month_line1= " Apr May Jun\n"; $month_line2= " Jul Aug Sep\n"; $month_line3= " Oct Nov Dec\n"; @month_line=($month_line0,$month_line1,$month_line2,$month_line3); @month_length=(31,28,31,30,31,30,31,31,30,31,30,31); $upack=" 1 2 3 4 5 6 7 8 91011121314151617181920212223242526272829303132"; sub calc_jd { my ($year,$month,$day,$is_greg)=@_; if($month<=2) { $year0=$year-1; $month0=$month+12; } else { $year0=$year; $month0=$month; } if(is_greg&& ($year>1582 || ($year==1582&&($month>10 || $month==10 && $day>=15)))) { $b=2-int($year0/100)+int($year0/400); } else { $b=0; } return int(365.25*$year0)+int(30.6001*($month0+1))+$day+1720994.5+$b; } sub calc_weekday { return int(($_[0]+1.5)%7); } sub is_leap { return $_[0]%4==0 && ($_[0]%100!=0 || $_[0]%400==0); } sub find_year { my ($from,$year) = @_; my $leap=is_leap($year); my $incr=$leap?4:1; my $day=int(calc_jd($year,1,1,1)%7); if($leap) { $from=($from+3)&~3; } for(;;) { $day2=int(calc_jd($from,1,1,1)%7); if($from!=$year && $day==$day2 && $leap==is_leap($from)) { last; } $from+=$incr; } return $from; } sub main { my $year_this_s=$ENV{QUERY_STRING}; my $cgi = 1; if($year_this_s) { $year_this_s =~ /year=([0-9]*)/; $year_this = $1; } else { $year_this = @ARGV[0] + 0; $cgi = 0; } if($year_this>1582 && $year_this<10000) { my $year_next=find_year($year_this,$year_this); my $year_196X=find_year(1964,$year_this); if ($cgi) { printf("Content-type:text/html\n\n%d Snoopy Calendar\n",$year_196X); print ("
\n");
        }
        printf($fmt_sn0,$year_196X);
        printf($fmt_sn1a,$year_this,$year_next,$year_next<=9999?" ":"",$fmt_sn1b);
        print (@fmt_sn2);
        printf($fmt_year,$year_196X);

        my $weekday=calc_weekday(calc_jd($year_196X,1,1,1));
        for($i=0;$i<4;$i++)
          { print $month_line[$i];
            print $week_line;
            my $row_size=74;
            my $buf=" " x ($row_size*6);
            for($j=0;$j<3;$j++)
              { my $row=0;
                my $ml=$month_length[$i*3+$j];
                if($ml==28 && is_leap($year_196X))
                  { $ml=29;
                  }
                for($k=0;$k<$ml;$k++)
                  { substr($buf,$row*$row_size+$weekday*3+$j*23+7,2)=substr($upack,(($k&0x1f)<<1),2);
                    if(++$weekday==7)
                      { $weekday=0;
                        $row++;
                      }
                  }
              }
            substr($buf,  $row_size-1,1)="\n";
            substr($buf,2*$row_size-1,1)="\n";
            substr($buf,3*$row_size-1,1)="\n";
            substr($buf,4*$row_size-1,1)="\n";
            substr($buf,5*$row_size-1,1)="\n";
            substr($buf,6*$row_size-1,1)="\n";
            print $buf;
          }
        if ($cgi) {
            print("
\n"); } } else { if ($cgi) { print("Content-type:text/html\n\nRange error\n

"); } printf("The year %d is out of range: 1583..9999\n", $year_this); if ($cgi) { print("

\n"); } } } main();