summaryrefslogtreecommitdiff
path: root/appl/cmd/cal.b
diff options
context:
space:
mode:
authorCharles.Forsyth <devnull@localhost>2006-12-22 17:07:39 +0000
committerCharles.Forsyth <devnull@localhost>2006-12-22 17:07:39 +0000
commit37da2899f40661e3e9631e497da8dc59b971cbd0 (patch)
treecbc6d4680e347d906f5fa7fca73214418741df72 /appl/cmd/cal.b
parent54bc8ff236ac10b3eaa928fd6bcfc0cdb2ba46ae (diff)
20060303a
Diffstat (limited to 'appl/cmd/cal.b')
-rw-r--r--appl/cmd/cal.b295
1 files changed, 295 insertions, 0 deletions
diff --git a/appl/cmd/cal.b b/appl/cmd/cal.b
new file mode 100644
index 00000000..90c4f777
--- /dev/null
+++ b/appl/cmd/cal.b
@@ -0,0 +1,295 @@
+implement Cal;
+
+#
+# Copyright © 1995-2002 Lucent Technologies Inc. All rights reserved.
+# Limbo transliteration 2003 by Vita Nuova
+# This software is subject to the Plan 9 Open Source Licence.
+#
+
+include "sys.m";
+ sys: Sys;
+
+include "draw.m";
+
+include "bufio.m";
+ bufio: Bufio;
+ Iobuf: import bufio;
+
+include "daytime.m";
+ daytime: Daytime;
+ Tm: import daytime;
+
+Cal: module
+{
+ init: fn(nil: ref Draw->Context, nil: list of string);
+};
+
+dayw := " S M Tu W Th F S";
+smon := array[] of {
+ "January", "February", "March", "April",
+ "May", "June", "July", "August",
+ "September", "October", "November", "December",
+};
+
+mon := array[] of {
+ 0,
+ 31, 29, 31, 30,
+ 31, 30, 31, 31,
+ 30, 31, 30, 31,
+};
+
+bout: ref Iobuf;
+
+init(nil: ref Draw->Context, args: list of string)
+{
+ y, m: int;
+
+ sys = load Sys Sys->PATH;
+ bufio = load Bufio Bufio->PATH;
+ daytime = load Daytime Daytime->PATH;
+
+ argc := len args;
+ if(argc > 3){
+ sys->fprint(sys->fildes(2), "usage: cal [month] [year]\n");
+ raise "fail:usage";
+ }
+ bout = bufio->fopen(sys->fildes(1), Bufio->OWRITE);
+
+#
+# no arg, print current month
+#
+ if(argc <= 1) {
+ m = curmo();
+ y = curyr();
+ return xshort(m, y);
+ }
+ args = tl args;
+
+#
+# one arg
+# if looks like a month, print month
+# else print year
+#
+ if(argc == 2) {
+ y = number(hd args);
+ if(y < 0)
+ y = -y;
+ if(y >= 1 && y <= 12)
+ return xshort(y, curyr());
+ return xlong(y);
+ }
+
+#
+# two arg, month and year
+#
+ m = number(hd args);
+ if(m < 0)
+ m = -m;
+ y = number(hd tl args);
+ return xshort(m, y);
+}
+
+#
+# print out just month
+#
+xshort(m: int, y: int)
+{
+ if(m < 1 || m > 12)
+ badarg();
+ if(y < 1 || y > 9999)
+ badarg();
+ bout.puts(sys->sprint(" %s %ud\n", smon[m-1], y));
+ bout.puts(sys->sprint("%s\n", dayw));
+ lines := cal(m, y);
+ for(i := 0; i < len lines; i++){
+ bout.puts(lines[i]);
+ bout.putc('\n');
+ }
+ bout.flush();
+}
+
+#
+# print out complete year
+#
+xlong(y: int)
+{
+ if(y<1 || y>9999)
+ badarg();
+ bout.puts("\n\n\n");
+ bout.puts(sys->sprint(" %ud\n", y));
+ bout.putc('\n');
+ months := array[3] of array of string;
+ for(i:=0; i<12; i+=3) {
+ bout.puts(sys->sprint(" %.3s", smon[i]));
+ bout.puts(sys->sprint(" %.3s", smon[i+1]));
+ bout.puts(sys->sprint(" %.3s\n", smon[i+2]));
+ bout.puts(sys->sprint("%s %s %s\n", dayw, dayw, dayw));
+ for(j := 0; j < 3; j++)
+ months[j] = cal(i+j+1, y);
+ for(l := 0; l < 6; l++){
+ s := "";
+ for(j = 0; j < 3; j++)
+ s += sys->sprint("%-20.20s ", months[j][l]);
+ for(j = len s; j > 0 && s[j-1] == ' ';)
+ j--;
+ bout.puts(s[0:j]);
+ bout.putc('\n');
+ }
+ }
+ bout.flush();
+}
+
+badarg()
+{
+ sys->fprint(sys->fildes(2), "cal: bad argument\n");
+ raise "fail:bad argument";
+}
+
+dict := array[] of {
+ ("january", 1),
+ ("february", 2),
+ ("march", 3),
+ ("april", 4),
+ ("may", 5),
+ ("june", 6),
+ ("july", 7),
+ ("august", 8),
+ ("sept", 9),
+ ("september", 9),
+ ("october", 10),
+ ("november", 11),
+ ("december", 12),
+};
+
+#
+# convert to a number.
+# if its a dictionary word,
+# return negative number
+#
+number(s: string): int
+{
+ if(len s >= 3){
+ for(n:=0; n < len dict; n++){
+ (word, val) := dict[n];
+ if(s == word || s == word[0:3])
+ return -val;
+ }
+ }
+ n := 0;
+ for(i := 0; i < len s; i++){
+ c := s[i];
+ if(c<'0' || c>'9')
+ badarg();
+ n = n*10 + c-'0';
+ }
+ return n;
+}
+
+pstr(str: string, n: int)
+{
+ bout.puts(sys->sprint("%-*.*s\n", n, n, str));
+}
+
+cal(m: int, y: int): array of string
+{
+ d := jan1(y);
+ mon[9] = 30;
+
+ case (jan1(y+1)+7-d)%7 {
+
+ #
+ # non-leap year
+ #
+ 1 =>
+ mon[2] = 28;
+
+ #
+ # leap year
+ #
+ 2 =>
+ mon[2] = 29;
+
+ #
+ # 1752
+ #
+ * =>
+ mon[2] = 29;
+ mon[9] = 19;
+ }
+ for(i:=1; i<m; i++)
+ d += mon[i];
+ d %= 7;
+ lines := array[6] of string;
+ l := 0;
+ s := "";
+ for(i = 0; i < d; i++)
+ s += " ";
+ for(i=1; i<=mon[m]; i++) {
+ if(i==3 && mon[m]==19) {
+ i += 11;
+ mon[m] += 11;
+ }
+ s += sys->sprint("%2d", i);
+ if(++d == 7) {
+ d = 0;
+ lines[l++] = s;
+ s = "";
+ }else
+ s[len s] = ' ';
+ }
+ if(s != nil){
+ while(s[len s-1] == ' ')
+ s = s[:len s-1];
+ lines[l] = s;
+ }
+ return lines;
+}
+
+#
+# return day of the week
+# of jan 1 of given year
+#
+jan1(y: int): int
+{
+#
+# normal gregorian calendar
+# one extra day per four years
+#
+
+ d := 4+y+(y+3)/4;
+
+#
+# julian calendar
+# regular gregorian
+# less three days per 400
+#
+
+ if(y > 1800) {
+ d -= (y-1701)/100;
+ d += (y-1601)/400;
+ }
+
+#
+# great calendar changeover instant
+#
+
+ if(y > 1752)
+ d += 3;
+
+ return d%7;
+}
+
+#
+# get current month and year
+#
+curmo(): int
+{
+ tm := daytime->local(daytime->now());
+ return tm.mon+1;
+}
+
+curyr(): int
+{
+ tm := daytime->local(daytime->now());
+ return tm.year+1900;
+}