diff options
| author | Charles.Forsyth <devnull@localhost> | 2006-12-22 17:07:39 +0000 |
|---|---|---|
| committer | Charles.Forsyth <devnull@localhost> | 2006-12-22 17:07:39 +0000 |
| commit | 37da2899f40661e3e9631e497da8dc59b971cbd0 (patch) | |
| tree | cbc6d4680e347d906f5fa7fca73214418741df72 /appl/cmd/cal.b | |
| parent | 54bc8ff236ac10b3eaa928fd6bcfc0cdb2ba46ae (diff) | |
20060303a
Diffstat (limited to 'appl/cmd/cal.b')
| -rw-r--r-- | appl/cmd/cal.b | 295 |
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; +} |
