cal.c - 9base - revived minimalist port of Plan 9 userland to Unix
 (HTM) git clone git://git.suckless.org/9base
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       cal.c (4204B)
       ---
            1 #include <u.h>
            2 #include <libc.h>
            3 #include <bio.h>
            4 
            5 char        dayw[] =
            6 {
            7         " S  M Tu  W Th  F  S"
            8 };
            9 char        *smon[] =
           10 {
           11         "January", "February", "March", "April",
           12         "May", "June", "July", "August",
           13         "September", "October", "November", "December",
           14 };
           15 char        mon[] =
           16 {
           17         0,
           18         31, 29, 31, 30,
           19         31, 30, 31, 31,
           20         30, 31, 30, 31,
           21 };
           22 char        string[432];
           23 Biobuf        bout;
           24 
           25 void        main(int argc, char *argv[]);
           26 int        number(char *str);
           27 void        pstr(char *str, int n);
           28 void        cal(int m, int y, char *p, int w);
           29 int        jan1(int yr);
           30 int        curmo(void);
           31 int        curyr(void);
           32 
           33 void
           34 main(int argc, char *argv[])
           35 {
           36         int y, i, j, m;
           37 
           38         if(argc > 3) {
           39                 fprint(2, "usage: cal [month] [year]\n");
           40                 exits("usage");
           41         }
           42         Binit(&bout, 1, OWRITE);
           43 
           44 /*
           45  * no arg, print current month
           46  */
           47         if(argc == 1) {
           48                 m = curmo();
           49                 y = curyr();
           50                 goto xshort;
           51         }
           52 
           53 /*
           54  * one arg
           55  *        if looks like a month, print month
           56  *        else print year
           57  */
           58         if(argc == 2) {
           59                 y = number(argv[1]);
           60                 if(y < 0)
           61                         y = -y;
           62                 if(y >= 1 && y <= 12) {
           63                         m = y;
           64                         y = curyr();
           65                         goto xshort;
           66                 }
           67                 goto xlong;
           68         }
           69 
           70 /*
           71  * two arg, month and year
           72  */
           73         m = number(argv[1]);
           74         if(m < 0)
           75                 m = -m;
           76         y = number(argv[2]);
           77         goto xshort;
           78 
           79 /*
           80  *        print out just month
           81  */
           82 xshort:
           83         if(m < 1 || m > 12)
           84                 goto badarg;
           85         if(y < 1 || y > 9999)
           86                 goto badarg;
           87         Bprint(&bout, "   %s %d\n", smon[m-1], y);
           88         Bprint(&bout, "%s\n", dayw);
           89         cal(m, y, string, 24);
           90         for(i=0; i<6*24; i+=24)
           91                 pstr(string+i, 24);
           92         exits(0);
           93 
           94 /*
           95  *        print out complete year
           96  */
           97 xlong:
           98         y = number(argv[1]);
           99         if(y<1 || y>9999)
          100                 goto badarg;
          101         Bprint(&bout, "\n\n\n");
          102         Bprint(&bout, "                                %d\n", y);
          103         Bprint(&bout, "\n");
          104         for(i=0; i<12; i+=3) {
          105                 for(j=0; j<6*72; j++)
          106                         string[j] = '\0';
          107                 Bprint(&bout, "         %.3s", smon[i]);
          108                 Bprint(&bout, "                    %.3s", smon[i+1]);
          109                 Bprint(&bout, "                    %.3s\n", smon[i+2]);
          110                 Bprint(&bout, "%s   %s   %s\n", dayw, dayw, dayw);
          111                 cal(i+1, y, string, 72);
          112                 cal(i+2, y, string+23, 72);
          113                 cal(i+3, y, string+46, 72);
          114                 for(j=0; j<6*72; j+=72)
          115                         pstr(string+j, 72);
          116         }
          117         Bprint(&bout, "\n\n\n");
          118         exits(0);
          119 
          120 badarg:
          121         Bprint(&bout, "cal: bad argument\n");
          122 }
          123 
          124 struct
          125 {
          126         char*        word;
          127         int        val;
          128 } dict[] =
          129 {
          130         "jan",                1,
          131         "january",        1,
          132         "feb",                2,
          133         "february",        2,
          134         "mar",                3,
          135         "march",        3,
          136         "apr",                4,
          137         "april",        4,
          138         "may",                5,
          139         "jun",                6,
          140         "june",                6,
          141         "jul",                7,
          142         "july",                7,
          143         "aug",                8,
          144         "august",        8,
          145         "sep",                9,
          146         "sept",                9,
          147         "september",        9,
          148         "oct",                10,
          149         "october",        10,
          150         "nov",                11,
          151         "november",        11,
          152         "dec",                12,
          153         "december",        12,
          154         0
          155 };
          156 
          157 /*
          158  * convert to a number.
          159  * if its a dictionary word,
          160  * return negative  number
          161  */
          162 int
          163 number(char *str)
          164 {
          165         int n, c;
          166         char *s;
          167 
          168         for(n=0; s=dict[n].word; n++)
          169                 if(strcmp(s, str) == 0)
          170                         return -dict[n].val;
          171         n = 0;
          172         s = str;
          173         while(c = *s++) {
          174                 if(c<'0' || c>'9')
          175                         return 0;
          176                 n = n*10 + c-'0';
          177         }
          178         return n;
          179 }
          180 
          181 void
          182 pstr(char *str, int n)
          183 {
          184         int i;
          185         char *s;
          186 
          187         s = str;
          188         i = n;
          189         while(i--)
          190                 if(*s++ == '\0')
          191                         s[-1] = ' ';
          192         i = n+1;
          193         while(i--)
          194                 if(*--s != ' ')
          195                         break;
          196         s[1] = '\0';
          197         Bprint(&bout, "%s\n", str);
          198 }
          199 
          200 void
          201 cal(int m, int y, char *p, int w)
          202 {
          203         int d, i;
          204         char *s;
          205 
          206         s = p;
          207         d = jan1(y);
          208         mon[2] = 29;
          209         mon[9] = 30;
          210 
          211         switch((jan1(y+1)+7-d)%7) {
          212 
          213         /*
          214          *        non-leap year
          215          */
          216         case 1:
          217                 mon[2] = 28;
          218                 break;
          219 
          220         /*
          221          *        1752
          222          */
          223         default:
          224                 mon[9] = 19;
          225                 break;
          226 
          227         /*
          228          *        leap year
          229          */
          230         case 2:
          231                 ;
          232         }
          233         for(i=1; i<m; i++)
          234                 d += mon[i];
          235         d %= 7;
          236         s += 3*d;
          237         for(i=1; i<=mon[m]; i++) {
          238                 if(i==3 && mon[m]==19) {
          239                         i += 11;
          240                         mon[m] += 11;
          241                 }
          242                 if(i > 9)
          243                         *s = i/10+'0';
          244                 s++;
          245                 *s++ = i%10+'0';
          246                 s++;
          247                 if(++d == 7) {
          248                         d = 0;
          249                         s = p+w;
          250                         p = s;
          251                 }
          252         }
          253 }
          254 
          255 /*
          256  *        return day of the week
          257  *        of jan 1 of given year
          258  */
          259 int
          260 jan1(int yr)
          261 {
          262         int y, d;
          263 
          264 /*
          265  *        normal gregorian calendar
          266  *        one extra day per four years
          267  */
          268 
          269         y = yr;
          270         d = 4+y+(y+3)/4;
          271 
          272 /*
          273  *        julian calendar
          274  *        regular gregorian
          275  *        less three days per 400
          276  */
          277 
          278         if(y > 1800) {
          279                 d -= (y-1701)/100;
          280                 d += (y-1601)/400;
          281         }
          282 
          283 /*
          284  *        great calendar changeover instant
          285  */
          286 
          287         if(y > 1752)
          288                 d += 3;
          289 
          290         return d%7;
          291 }
          292 
          293 /*
          294  * system dependent
          295  * get current month and year
          296  */
          297 int
          298 curmo(void)
          299 {
          300         Tm *tm;
          301 
          302         tm = localtime(time(0));
          303         return tm->mon+1;
          304 }
          305 
          306 int
          307 curyr(void)
          308 {
          309         Tm *tm;
          310 
          311         tm = localtime(time(0));
          312         return tm->year+1900;
          313 }