Calendar - for "REAL" programmers: Difference between revisions

From Rosetta Code
Content added Content deleted
(→‎{{header|UNIX Shell}}: Make it actually qualify)
Line 3,007: Line 3,007:


=={{header|UNIX Shell}}==
=={{header|UNIX Shell}}==
<lang shell>cal -m 1969 | tr a-z A-Z</lang>
<lang shell>CAL=CAL
TR=TR
A=A
Z=Z
LANG=C ${CAL,,} 1969 | ${TR,,} ${A,}-${Z,} A-Z</lang>
{{out}}
{{out}}
<pre>
<pre>

Revision as of 00:00, 10 August 2018

Task
Calendar - for "REAL" programmers
You are encouraged to solve this task according to the task description, using any language you may know.
Task

Provide an algorithm as per the Calendar task, except the entire code for the algorithm must be presented   entirely without lowercase.

Also - as per many 1969 era line printers - format the calendar to nicely fill a page that is 132 characters wide.

(Hint: manually convert the code from the Calendar task to all UPPERCASE)

This task also is inspired by Real Programmers Don't Use PASCAL by Ed Post, Datamation, volume 29 number 7, July 1983.

THE REAL PROGRAMMER'S NATURAL HABITAT
"Taped to the wall is a line-printer Snoopy calender for the year 1969."

Moreover this task is further inspired by the long lost corollary article titled:

"Real programmers think in UPPERCASE"!

Note: Whereas today we only need to worry about ASCII, UTF-8, UTF-16, UTF-32, UTF-7 and UTF-EBCDIC encodings, in the 1960s having code in UPPERCASE was often mandatory as characters were often stuffed into 36-bit words as 6 lots of 6-bit characters. More extreme words sizes include 60-bit words of the CDC 6000 series computers. The Soviets even had a national character set that was inclusive of all 4-bit, 5-bit, 6-bit & 7-bit depending on how the file was opened... And one rogue Soviet university went further and built a 1.5-bit based computer.

Of course... as us Boomers have turned into Geezers we have become HARD OF HEARING, and suffer from chronic Presbyopia, hence programming in UPPERCASE is less to do with computer architecture and more to do with practically. :-)

For economy of size, do not actually include Snoopy generation in either the code or the output, instead just output a place-holder.

FYI: a nice ASCII art file of Snoopy can be found at textfiles.com. Save with a .txt extension.

Trivia: The terms uppercase and lowercase date back to the early days of the mechanical printing press. Individual metal alloy casts of each needed letter, or punctuation symbol, were meticulously added to a press block, by hand, before rolling out copies of a page. These metal casts were stored and organized in wooden cases. The more often needed miniscule letters were placed closer to hand, in the lower cases of the work bench. The less often needed, capitalized, majiscule letters, ended up in the harder to reach upper cases.

360 Assembly

This is for real programmers who code only in assembler :). The code could have been run in april 1964, punched on 80-column cards, read on a card reader, and printed with a 132-column line printer on fan-folded paper with perforated edges. <lang 360asm>* CALENDAR FOR REAL PROGRAMMERS 05/03/2017 CALENDAR CSECT

        USING  CALENDAR,R13       BASE REGISTER
        B      72(R15)            SKIP MY SAVEAREA
        DC     17F'0'             MY SAVEAREA
        STM    R14,R12,12(R13)    SAVE CALLER'S REGISTERS
        ST     R13,4(R15)         LINK BACKWARD
        ST     R15,8(R13)         LINK FORWARD 
        LR     R13,R15            SET ADDRESSABILITY
        L      R4,YEAR            YEAR
        SRDA   R4,32              .
        D      R4,=F'4'           YEAR//4
        LTR    R4,R4              IF YEAR//4=0
        BNZ    LYNOT
        L      R4,YEAR            YEAR
        SRDA   R4,32              .
        D      R4,=F'100'         YEAR//100
        LTR    R4,R4              IF YEAR//100=0
        BNZ    LY 
        L      R4,YEAR            YEAR
        SRDA   R4,32              .
        D      R4,=F'400'         IF YEAR//400
        LTR    R4,R4              IF YEAR//400=0
        BNZ    LYNOT

LY MVC ML+2,=H'29' ML(2)=29 LEAPYEAR LYNOT SR R10,R10 LTD1=0

        LA     R6,1               I=1

LOOPI1 C R6,=F'31' DO I=1 TO 31

        BH     ELOOPI1
        XDECO  R6,XDEC            EDIT I
        LA     R14,TD1            TD1
        AR     R14,R10            TD1+LTD1
        MVC    0(3,R14),XDEC+9    SUB(TD1,LTD1+1,3)=PIC(I,3)
        LA     R10,3(R10)         LTD1+3
        LA     R6,1(R6)           I=I+1
        B      LOOPI1

ELOOPI1 LA R6,1 I=1 LOOPI2 C R6,=F'12' DO I=1 TO 12

        BH     ELOOPI2
        ST     R6,M               M=I
        MVC    D,=F'1'            D=1
        MVC    YY,YEAR            YY=YEAR
        L      R4,M               M
        C      R4,=F'3'           IF M<3
        BNL    GE3
        L      R2,M               M
        LA     R2,12(R2)          M+12
        ST     R2,M               M=M+12
        L      R2,YY              YY
        BCTR   R2,0               YY-1
        ST     R2,YY              YY=YY-1

GE3 L R2,YY YY

        LR     R1,R2              YY
        SRA    R1,2               YY/4
        AR     R2,R1              YY+(YY/4)         
        L      R4,YY              YY
        SRDA   R4,32              .
        D      R4,=F'100'         YY/100      
        SR     R2,R5              YY+(YY/4)-(YY/100)
        L      R4,YY              YY
        SRDA   R4,32              .
        D      R4,=F'400'         YY/400                          
        AR     R2,R5              YY+(YY/4)-(YY/100)+(YY/400)  
        A      R2,D               R2=YY+(YY/4)-(YY/100)+(YY/400)+D
        LA     R5,153             153 
        M      R4,M               153*M            
        LA     R5,8(R5)           153*M+8                                     
        D      R4,=F'5'           (153*M+8)/5               
        AR     R5,R2              ((153*M+8)/5+R2  
        LA     R4,0               .
        D      R4,=F'7'           R4=MOD(R5,7)  0=SUN 1=MON ... 6=SAT                  
        LTR    R4,R4              IF J=0
        BNZ    JNE0
        LA     R4,7               J=7

JNE0 BCTR R4,0 J-1

        MH     R4,=H'3'           J*3
        LR     R10,R4             J1=J*3
        LR     R1,R6              I
        SLA    R1,1               *2
        LH     R11,ML-2(R1)       ML(I)
        MH     R11,=H'3'          J2=ML(I)*3
        MVC    TD2,BLANK          TD2=' '
        LA     R4,TD1             @TD1
        LR     R5,R11             J2
        LA     R2,TD2             @TD2
        AR     R2,R10             @TD2+J1
        LR     R3,R5              J2
        MVCL   R2,R4              SUB(TD2,J1+1,J2)=SUB(TD1,1,J2)
        LR     R1,R6              I
        MH     R1,=H'144'         *144
        LA     R14,DA-144(R1)     @DA(I)
        MVC    0(144,R14),TD2     DA(I)=TD2
        LA     R6,1(R6)           I=I+1
        B      LOOPI2

ELOOPI2 XPRNT SNOOPY,132 PRINT SNOOPY

        L      R1,YEAR            YEAR
        XDECO  R1,PG+56           EDIT YEAR
        XPRNT  PG,L'PG            PRINT YEAR
        MVC    WDLINE,BLANK       WDLINE=' '
        LA     R10,1              LWDLINE=1
        LA     R8,1               K=1 

LOOPK3 C R8,=F'6' DO K=1 TO 6

        BH     ELOOPK3
        LA     R4,WDLINE          @WDLINE
        AR     R4,R10             +LWDLINE
        MVC    0(20,R4),WDNA      SUB(WDLINE,LWDLINE+1,20)=WDNA
        LA     R10,20(R10)        LWDLINE=LWDLINE+20
        C      R8,=F'6'           IF K<6
        BNL    ITERK3
        LA     R10,2(R10)         LWDLINE=LWDLINE+2

ITERK3 LA R8,1(R8) K=K+1

        B      LOOPK3

ELOOPK3 LA R6,1 I=1 LOOPI4 C R6,=F'12' DO I=1 TO 12 BY 6

        BH     ELOOPI4
        MVC    MOLINE,BLANK       MOLINE=' '
        LA     R10,6              LMOLINE=6
        LR     R8,R6              K=I

LOOPK4 LA R2,5(R6) I+5

        CR     R8,R2              DO K=I TO I+5
        BH     ELOOPK4
        LR     R1,R8              K
        MH     R1,=H'10'          *10
        LA     R3,MO-10(R1)       MO(K)
        LA     R4,MOLINE          @MOLINE
        AR     R4,R10             +LMOLINE
        MVC    0(10,R4),0(R3)     SUB(MOLINE,LMOLINE+1,10)=MO(K)
        LA     R10,22(R10)        LMOLINE=LMOLINE+22
        LA     R8,1(R8)           K=K+1
        B      LOOPK4

ELOOPK4 XPRNT MOLINE,L'MOLINE PRINT MONTHS

        XPRNT  WDLINE,L'WDLINE    PRINT DAYS OF WEEK
        LA     R7,1               J=1

LOOPJ4 C R7,=F'106' DO J=1 TO 106 BY 21

        BH     ELOOPJ4
        MVC    PG,BLANK           CLEAR BUFFER
        LA     R9,PG              PGI=0
        LR     R8,R6              K=I

LOOPK5 LA R2,5(R6) I+5

        CR     R8,R2              DO K=I TO I+5
        BH     ELOOPK5
        LR     R1,R8              K
        MH     R1,=H'144'         *144
        LA     R4,DA-144(R1)      DA(K)
        BCTR   R4,0               -1
        AR     R4,R7              +J
        MVC    0(21,R9),0(R4)     SUBSTR(DA(K),J,21)
        LA     R9,22(R9)          PGI=PGI+22
        LA     R8,1(R8)           K=K+1
        B      LOOPK5

ELOOPK5 XPRNT PG,L'PG PRINT BUFFER

        LA     R7,21(R7)          J=J+21
        B      LOOPJ4

ELOOPJ4 LA R6,6(R6) I=I+6

        B      LOOPI4

ELOOPI4 L R13,4(0,R13) RESTORE PREVIOUS SAVEAREA POINTER

        LM     R14,R12,12(R13)    RESTORE CALLER'S REGISTERS
        XR     R15,R15            SET RETURN CODE TO 0
        BR     R14                RETURN TO CALLER

SNOOPY DC CL57' ',CL18'INSERT SNOOPY HERE',CL57' ' YEAR DC F'1969' <== 1969 MO DC CL10' JANUARY ',CL10' FEBRUARY ',CL10' MARCH '

        DC     CL10'  APRIL   ',CL10'   MAY    ',CL10'   JUNE   '
        DC     CL10'   JULY   ',CL10'  AUGUST  ',CL10'SEPTEMBER '
        DC     CL10' OCTOBER  ',CL10' NOVEMBER ',CL10' DECEMBER '

ML DC H'31',H'28',H'31',H'30',H'31',H'30'

        DC     H'31',H'31',H'30',H'31',H'30',H'31'

WDNA DC CL20'MO TU WE TH FR SA SU' M DS F D DS F YY DS F TD1 DS CL93 TD2 DS CL144 MOLINE DS CL132 WDLINE DS CL132 PG DC CL132' ' BUFFER FOR THE LINE PRINTER XDEC DS CL12 BLANK DC CL144' ' DA DS 12CL144

        YREGS
        END    CALENDAR</lang>
Output:
                                                         INSERT SNOOPY HERE
                                                                1969
       JANUARY               FEBRUARY               MARCH                 APRIL                  MAY                   JUNE
 MO TU WE TH FR SA SU  MO TU WE TH FR SA SU  MO TU WE TH FR SA SU  MO TU WE TH FR SA SU  MO TU WE TH FR SA SU  MO TU WE TH FR SA SU
        1  2  3  4  5                  1  2                  1  2      1  2  3  4  5  6            1  2  3  4                     1
  6  7  8  9 10 11 12   3  4  5  6  7  8  9   3  4  5  6  7  8  9   7  8  9 10 11 12 13   5  6  7  8  9 10 11   2  3  4  5  6  7  8
 13 14 15 16 17 18 19  10 11 12 13 14 15 16  10 11 12 13 14 15 16  14 15 16 17 18 19 20  12 13 14 15 16 17 18   9 10 11 12 13 14 15
 20 21 22 23 24 25 26  17 18 19 20 21 22 23  17 18 19 20 21 22 23  21 22 23 24 25 26 27  19 20 21 22 23 24 25  16 17 18 19 20 21 22
 27 28 29 30 31        24 25 26 27 28        24 25 26 27 28 29 30  28 29 30              26 27 28 29 30 31     23 24 25 26 27 28 29
                                             31                                                                30
         JULY                 AUGUST              SEPTEMBER              OCTOBER               NOVEMBER              DECEMBER
 MO TU WE TH FR SA SU  MO TU WE TH FR SA SU  MO TU WE TH FR SA SU  MO TU WE TH FR SA SU  MO TU WE TH FR SA SU  MO TU WE TH FR SA SU
     1  2  3  4  5  6               1  2  3   1  2  3  4  5  6  7         1  2  3  4  5                  1  2   1  2  3  4  5  6  7
  7  8  9 10 11 12 13   4  5  6  7  8  9 10   8  9 10 11 12 13 14   6  7  8  9 10 11 12   3  4  5  6  7  8  9   8  9 10 11 12 13 14
 14 15 16 17 18 19 20  11 12 13 14 15 16 17  15 16 17 18 19 20 21  13 14 15 16 17 18 19  10 11 12 13 14 15 16  15 16 17 18 19 20 21
 21 22 23 24 25 26 27  18 19 20 21 22 23 24  22 23 24 25 26 27 28  20 21 22 23 24 25 26  17 18 19 20 21 22 23  22 23 24 25 26 27 28
 28 29 30 31           25 26 27 28 29 30 31  29 30                 27 28 29 30 31        24 25 26 27 28 29 30  29 30 31

Ada

In Ada, the task is really easy, because Ada is case insensitive. I.e., one could simply replicate the code from Ada solution of the calendar task and convert every lowercase character to uppercase. Instead of doing that, the implementation below reuses the package "PRINTABLE_CALENDAR" (same as "Printable_Calendar" or "printable_calendar") from the calendar task:

<lang Ada>WITH PRINTABLE_CALENDAR;

PROCEDURE REAL_CAL IS

  C: PRINTABLE_CALENDAR.CALENDAR := PRINTABLE_CALENDAR.INIT_132
    ((WEEKDAY_REP =>
         "MO TU WE TH FR SA SO",
      MONTH_REP   =>
        ("      JANUARY       ", "      FEBRUARY      ",
         "       MARCH        ", "       APRIL        ",
         "        MAY         ", "        JUNE        ",
         "        JULY        ", "       AUGUST       ",
         "      SEPTEMBER     ", "       OCTOBER      ",
         "      NOVEMBER      ", "      DECEMBER      ")
     ));

BEGIN

  C.PRINT_LINE_CENTERED("[SNOOPY]");
  C.NEW_LINE;
  C.PRINT(1969, "NINETEEN-SIXTY-NINE");

END REAL_CAL;</lang>

Output:
                                                             [SNOOPY]                                                             

                                                        NINETEEN-SIXTY-NINE                                                        

       JANUARY               FEBRUARY               MARCH                 APRIL                  MAY                   JUNE        
 MO TU WE TH FR SA SO  MO TU WE TH FR SA SO  MO TU WE TH FR SA SO  MO TU WE TH FR SA SO  MO TU WE TH FR SA SO  MO TU WE TH FR SA SO
        1  2  3  4  5                  1  2                  1  2      1  2  3  4  5  6            1  2  3  4                     1
  6  7  8  9 10 11 12   3  4  5  6  7  8  9   3  4  5  6  7  8  9   7  8  9 10 11 12 13   5  6  7  8  9 10 11   2  3  4  5  6  7  8
 13 14 15 16 17 18 19  10 11 12 13 14 15 16  10 11 12 13 14 15 16  14 15 16 17 18 19 20  12 13 14 15 16 17 18   9 10 11 12 13 14 15
 20 21 22 23 24 25 26  17 18 19 20 21 22 23  17 18 19 20 21 22 23  21 22 23 24 25 26 27  19 20 21 22 23 24 25  16 17 18 19 20 21 22
 27 28 29 30 31        24 25 26 27 28        24 25 26 27 28 29 30  28 29 30              26 27 28 29 30 31     23 24 25 26 27 28 29
                                             31                                                                30                  

         JULY                 AUGUST               SEPTEMBER              OCTOBER              NOVEMBER              DECEMBER      
 MO TU WE TH FR SA SO  MO TU WE TH FR SA SO  MO TU WE TH FR SA SO  MO TU WE TH FR SA SO  MO TU WE TH FR SA SO  MO TU WE TH FR SA SO
     1  2  3  4  5  6               1  2  3   1  2  3  4  5  6  7         1  2  3  4  5                  1  2   1  2  3  4  5  6  7
  7  8  9 10 11 12 13   4  5  6  7  8  9 10   8  9 10 11 12 13 14   6  7  8  9 10 11 12   3  4  5  6  7  8  9   8  9 10 11 12 13 14
 14 15 16 17 18 19 20  11 12 13 14 15 16 17  15 16 17 18 19 20 21  13 14 15 16 17 18 19  10 11 12 13 14 15 16  15 16 17 18 19 20 21
 21 22 23 24 25 26 27  18 19 20 21 22 23 24  22 23 24 25 26 27 28  20 21 22 23 24 25 26  17 18 19 20 21 22 23  22 23 24 25 26 27 28
 28 29 30 31           25 26 27 28 29 30 31  29 30                 27 28 29 30 31        24 25 26 27 28 29 30  29 30 31  

To change the output to 80-character devices, replace "INIT_132" by "INIT_80".

ALGOL 68

Works with: ALGOL 68 version Revision 1 - no extensions to language used
Works with: ALGOL 68G version Any - tested with release 1.18.0-9h.tiny.

This code uses 'quote stropping' to mark reserved words, it is a very early form of wikitext and makes syntax highlighting of source code for publication relatively easy.

Note: to run this code with ALGOL 68G you need to use the --quote-stropping option. <lang algol68>'PR' QUOTE 'PR'

'PROC' PRINT CALENDAR = ('INT' YEAR, PAGE WIDTH)'VOID': 'BEGIN'

 ()'STRING' MONTH NAMES = (
     "JANUARY","FEBRUARY","MARCH","APRIL","MAY","JUNE",
     "JULY","AUGUST","SEPTEMBER","OCTOBER","NOVEMBER","DECEMBER"),
   WEEKDAY NAMES = ("SU","MO","TU","WE","TH","FR","SA");
 'FORMAT' WEEKDAY FMT = $G,N('UPB' WEEKDAY NAMES - 'LWB' WEEKDAY NAMES)(" "G)$;

 # 'JUGGLE' THE CALENDAR FORMAT TO FIT THE PRINTER/SCREEN WIDTH #
 'INT' DAY WIDTH = 'UPB' WEEKDAY NAMES(1), DAY GAP=1;
 'INT' MONTH WIDTH = (DAY WIDTH+DAY GAP) * 'UPB' WEEKDAY NAMES-1;
 'INT' MONTH HEADING LINES = 2;
 'INT' MONTH LINES = (31 'OVER' 'UPB' WEEKDAY NAMES+MONTH HEADING LINES+2); # +2 FOR HEAD/TAIL WEEKS #
 'INT' YEAR COLS = (PAGE WIDTH+1) 'OVER' (MONTH WIDTH+1);
 'INT' YEAR ROWS = ('UPB' MONTH NAMES-1)'OVER' YEAR COLS + 1;
 'INT' MONTH GAP = (PAGE WIDTH - YEAR COLS*MONTH WIDTH + 1)'OVER' YEAR COLS;
 'INT' YEAR WIDTH = YEAR COLS*(MONTH WIDTH+MONTH GAP)-MONTH GAP;
 'INT' YEAR LINES = YEAR ROWS*MONTH LINES;

 'MODE' 'MONTHBOX' = (MONTH LINES, MONTH WIDTH)'CHAR';
 'MODE' 'YEARBOX'  = (YEAR  LINES, YEAR  WIDTH)'CHAR';

 'INT' WEEK START = 1; # 'SUNDAY' #

 'PROC' DAYS IN MONTH = ('INT' YEAR, MONTH)'INT':
   'CASE' MONTH 'IN' 31,
     'IF' YEAR 'MOD' 4 'EQ' 0 'AND' YEAR 'MOD' 100 'NE' 0 'OR' YEAR 'MOD' 400 'EQ' 0 'THEN' 29 'ELSE' 28 'FI',
     31, 30, 31, 30, 31, 31, 30, 31, 30, 31
   'ESAC';

 'PROC' DAY OF WEEK = ('INT' YEAR, MONTH, DAY)'INT': 'BEGIN'
   # 'DAY' OF THE WEEK BY 'ZELLER'’S 'CONGRUENCE' ALGORITHM FROM 1887 #
   'INT' Y := YEAR, M := MONTH, D := DAY, C;
   'IF' M <= 2 'THEN' M +:= 12; Y -:= 1 'FI';
   C := Y 'OVER' 100;
   Y 'MODAB' 100;
   (D - 1 + ((M + 1) * 26) 'OVER' 10 + Y + Y 'OVER' 4 + C 'OVER' 4 - 2 * C) 'MOD' 7
 'END';

 'MODE' 'SIMPLEOUT' = 'UNION'('STRING', ()'STRING', 'INT');

 'PROC' CPUTF = ('REF'()'CHAR' OUT, 'FORMAT' FMT, 'SIMPLEOUT' ARGV)'VOID':'BEGIN'
   'FILE' F; 'STRING' S; ASSOCIATE(F,S);
   PUTF(F, (FMT, ARGV));
   OUT(:'UPB' S):=S;
   CLOSE(F)
 'END';

 'PROC' MONTH REPR = ('INT' YEAR, MONTH)'MONTHBOX':'BEGIN'
   'MONTHBOX' MONTH BOX; 'FOR' LINE 'TO' 'UPB' MONTH BOX 'DO' MONTH BOX(LINE,):=" "* 2 'UPB' MONTH BOX 'OD';
   'STRING' MONTH NAME = MONTH NAMES(MONTH);

 # CENTER THE TITLE #
   CPUTF(MONTH BOX(1,(MONTH WIDTH - 'UPB' MONTH NAME ) 'OVER' 2+1:), $G$, MONTH NAME);
   CPUTF(MONTH BOX(2,), WEEKDAY FMT, WEEKDAY NAMES);

   'INT' FIRST DAY := DAY OF WEEK(YEAR, MONTH, 1);
   'FOR' DAY 'TO' DAYS IN MONTH(YEAR, MONTH) 'DO'
     'INT' LINE = (DAY+FIRST DAY-WEEK START) 'OVER' 'UPB' WEEKDAY NAMES + MONTH HEADING LINES + 1;
     'INT' CHAR =((DAY+FIRST DAY-WEEK START) 'MOD' 'UPB' WEEKDAY NAMES)*(DAY WIDTH+DAY GAP) + 1;
     CPUTF(MONTH BOX(LINE,CHAR:CHAR+DAY WIDTH-1),$G(-DAY WIDTH)$, DAY)
   'OD';
   MONTH BOX
 'END';

 'PROC' YEAR REPR = ('INT' YEAR)'YEARBOX':'BEGIN'
   'YEARBOX' YEAR BOX;
   'FOR' LINE 'TO' 'UPB' YEAR BOX 'DO' YEAR BOX(LINE,):=" "* 2 'UPB' YEAR BOX 'OD';
   'FOR' MONTH ROW 'FROM' 0 'TO' YEAR ROWS-1 'DO'
     'FOR' MONTH COL 'FROM' 0 'TO' YEAR COLS-1 'DO'
       'INT' MONTH = MONTH ROW * YEAR COLS + MONTH COL + 1;
       'IF' MONTH > 'UPB' MONTH NAMES 'THEN'
         DONE
       'ELSE'
         'INT' MONTH COL WIDTH = MONTH WIDTH+MONTH GAP;
         YEAR BOX(
           MONTH ROW*MONTH LINES+1 : (MONTH ROW+1)*MONTH LINES,
           MONTH COL*MONTH COL WIDTH+1 : (MONTH COL+1)*MONTH COL WIDTH-MONTH GAP
         ) := MONTH REPR(YEAR, MONTH)
       'FI'
     'OD'
   'OD';
   DONE: YEAR BOX
 'END';

 'INT' CENTER = (YEAR COLS*(MONTH WIDTH+MONTH GAP) - MONTH GAP - 1) 'OVER' 2;
 'INT' INDENT = (PAGE WIDTH - YEAR WIDTH) 'OVER' 2;

 PRINTF((
   $N(INDENT + CENTER - 9)K  G L$, "(INSERT SNOOPY HERE)",
   $N(INDENT + CENTER - 1)K 4D L$, YEAR, $L$,
   $N(INDENT)K N(YEAR WIDTH)(G)  L$, YEAR REPR(YEAR)
 ))

'END';

MAIN: 'BEGIN' 'CO' INSPIRED BY HTTP://WWW.EE.RYERSON.CA/~ELF/hack/realmen.html

          REAL PROGRAMMERS DONT USE PASCAL - ED POST
           DATAMATION, VOLUME 29 NUMBER 7, JULY 1983
             THE REAL PROGRAMMERS NATURAL HABITAT

"TAPED TO THE WALL IS A LINE-PRINTER SNOOPY CALENDER FOR THE YEAR 1969" 'CO'

 'INT' MANKIND STEPPED ON THE MOON = 1969,
     LINE PRINTER WIDTH = 132; # AS AT 1969! #
 PRINT CALENDAR(MANKIND STEPPED ON THE MOON, LINE PRINTER WIDTH)

'END'</lang>

Output:
                                                       (INSERT SNOOPY HERE)
                                                               1969

      JANUARY               FEBRUARY               MARCH                 APRIL                  MAY                   JUNE        
SU MO TU WE TH FR SA  SU MO TU WE TH FR SA  SU MO TU WE TH FR SA  SU MO TU WE TH FR SA  SU MO TU WE TH FR SA  SU MO TU WE TH FR SA
          1  2  3  4                     1                     1         1  2  3  4  5               1  2  3   1  2  3  4  5  6  7
 5  6  7  8  9 10 11   2  3  4  5  6  7  8   2  3  4  5  6  7  8   6  7  8  9 10 11 12   4  5  6  7  8  9 10   8  9 10 11 12 13 14
12 13 14 15 16 17 18   9 10 11 12 13 14 15   9 10 11 12 13 14 15  13 14 15 16 17 18 19  11 12 13 14 15 16 17  15 16 17 18 19 20 21
19 20 21 22 23 24 25  16 17 18 19 20 21 22  16 17 18 19 20 21 22  20 21 22 23 24 25 26  18 19 20 21 22 23 24  22 23 24 25 26 27 28
26 27 28 29 30 31     23 24 25 26 27 28     23 24 25 26 27 28 29  27 28 29 30           25 26 27 28 29 30 31  29 30               
                                            30 31                                                                                 
        JULY                 AUGUST              SEPTEMBER              OCTOBER               NOVEMBER              DECEMBER      
SU MO TU WE TH FR SA  SU MO TU WE TH FR SA  SU MO TU WE TH FR SA  SU MO TU WE TH FR SA  SU MO TU WE TH FR SA  SU MO TU WE TH FR SA
       1  2  3  4  5                  1  2      1  2  3  4  5  6            1  2  3  4                     1      1  2  3  4  5  6
 6  7  8  9 10 11 12   3  4  5  6  7  8  9   7  8  9 10 11 12 13   5  6  7  8  9 10 11   2  3  4  5  6  7  8   7  8  9 10 11 12 13
13 14 15 16 17 18 19  10 11 12 13 14 15 16  14 15 16 17 18 19 20  12 13 14 15 16 17 18   9 10 11 12 13 14 15  14 15 16 17 18 19 20
20 21 22 23 24 25 26  17 18 19 20 21 22 23  21 22 23 24 25 26 27  19 20 21 22 23 24 25  16 17 18 19 20 21 22  21 22 23 24 25 26 27
27 28 29 30 31        24 25 26 27 28 29 30  28 29 30              26 27 28 29 30 31     23 24 25 26 27 28 29  28 29 30 31         
                      31                                                                30                                        

AutoHotkey

<lang AutoHotkey>CALENDAR(YR){ LASTDAY := [], DAY := [] TITLES = (LTRIM ______JANUARY_________________FEBRUARY_________________MARCH_______ _______APRIL____________________MAY____________________JUNE________ ________JULY___________________AUGUST_________________SEPTEMBER_____ ______OCTOBER_________________NOVEMBER________________DECEMBER______ ) STRINGSPLIT, TITLE, TITLES, % CHR(10) RES := "________________________________" YR CHR(13) CHR(10)

LOOP 4 { ; 4 VERTICAL SECTIONS DAY[1]:=YR SUBSTR("0" A_INDEX*3 -2, -1) 01 DAY[2]:=YR SUBSTR("0" A_INDEX*3 -1, -1) 01 DAY[3]:=YR SUBSTR("0" A_INDEX*3 , -1) 01 RES .= CHR(13) CHR(10) TITLE%A_INDEX% CHR(13) CHR(10) "SU MO TU WE TH FR SA SU MO TU WE TH FR SA SU MO TU WE TH FR SA" LOOP , 6 { ; 6 WEEKS MAX PER MONTH WEEK := A_INDEX, RES .= CHR(13) CHR(10) LOOP, 21 { ; 3 WEEKS TIMES 7 DAYS MON := CEIL(A_INDEX/7), THISWD := MOD(A_INDEX-1,7)+1 FORMATTIME, WD, % DAY[MON], WDAY ;~ MSGBOX % WD FORMATTIME, DD, % DAY[MON], % CHR(100) CHR(100) IF (WD>THISWD) { RES .= "__ " CONTINUE } DD := ((WEEK>3) && DD <10) ? "__" : DD, RES .= DD " ", LASTDAY[MON] := DAY[MON], DAY[MON] +=1, D RES .= ((WD=7) && A_INDEX < 21) ? "___" : "" FORMATTIME, DD, % DAY[MON], % CHR(100) CHR(100) } } RES .= CHR(13) CHR(10) } STRINGREPLACE, RES, RES,_,%A_SPACE%, ALL STRINGREPLACE, RES, RES,%A_SPACE%0,%A_SPACE%%A_SPACE%, ALL RETURN RES }</lang> Examples:<lang AutoHotkey>EXAMPLES: GUI, FONT,S8, COURIER GUI, ADD, EDIT, VYR W40 R1 LIMIT4 NUMBER, 1969 GUI, ADD, EDIT, VEDIT2 W580 R38 GUI, ADD, BUTTON, DEFAULT HIDDEN GSUBMIT GUI, SHOW

SUBMIT: GUI, SUBMIT, NOHIDE GUICONTROL,, EDIT2, % CALENDAR(YR) RETURN

GUIESCAPE: GUICLOSE: EXITAPP RETURN</lang>

Output:
                                1969

      JANUARY                 FEBRUARY                 MARCH       
SU MO TU WE TH FR SA    SU MO TU WE TH FR SA    SU MO TU WE TH FR SA
          1  2  3  4                       1                       1 
05  6  7  8  9 10 11     2  3  4  5  6  7  8     2  3  4  5  6  7  8 
12 13 14 15 16 17 18     9 10 11 12 13 14 15     9 10 11 12 13 14 15 
19 20 21 22 23 24 25    16 17 18 19 20 21 22    16 17 18 19 20 21 22 
26 27 28 29 30 31       23 24 25 26 27 28       23 24 25 26 27 28 29 
                                                30 31                

       APRIL                    MAY                    JUNE        
SU MO TU WE TH FR SA    SU MO TU WE TH FR SA    SU MO TU WE TH FR SA
       1  2  3  4  5                 1  2  3     1  2  3  4  5  6  7 
06  7  8  9 10 11 12     4  5  6  7  8  9 10     8  9 10 11 12 13 14 
13 14 15 16 17 18 19    11 12 13 14 15 16 17    15 16 17 18 19 20 21 
20 21 22 23 24 25 26    18 19 20 21 22 23 24    22 23 24 25 26 27 28 
27 28 29 30             25 26 27 28 29 30 31    29 30                
                                                                     

        JULY                   AUGUST                 SEPTEMBER     
SU MO TU WE TH FR SA    SU MO TU WE TH FR SA    SU MO TU WE TH FR SA
       1  2  3  4  5                    1  2        1  2  3  4  5  6 
06  7  8  9 10 11 12     3  4  5  6  7  8  9     7  8  9 10 11 12 13 
13 14 15 16 17 18 19    10 11 12 13 14 15 16    14 15 16 17 18 19 20 
20 21 22 23 24 25 26    17 18 19 20 21 22 23    21 22 23 24 25 26 27 
27 28 29 30 31          24 25 26 27 28 29 30    28 29 30             
                        31                                           

      OCTOBER                 NOVEMBER                DECEMBER      
SU MO TU WE TH FR SA    SU MO TU WE TH FR SA    SU MO TU WE TH FR SA
          1  2  3  4                       1        1  2  3  4  5  6 
05  6  7  8  9 10 11     2  3  4  5  6  7  8     7  8  9 10 11 12 13 
12 13 14 15 16 17 18     9 10 11 12 13 14 15    14 15 16 17 18 19 20 
19 20 21 22 23 24 25    16 17 18 19 20 21 22    21 22 23 24 25 26 27 
26 27 28 29 30 31       23 24 25 26 27 28 29    28 29 30 31          
                        30                                           

BaCon

Choosing 132 character output. Same as the "Calendar" from the calendar task but using all capitals: <lang freebasic>DECLARE MON$[] = { "JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUNE", "JULY", "AUGUST", "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER" } DECLARE MON[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } Y$ = "1969" ' Leap year INCR MON[1], IIF(MOD(VAL(Y$), 4) = 0 OR MOD(VAL(Y$), 100) = 0 AND MOD(VAL(Y$), 400) <> 0, 1, 0) PRINT ALIGN$("[SNOOPY HERE]", 132, 2) PRINT ALIGN$(Y$, 132, 2) FOR NR = 0 TO 11

   ROW = 3
   GOTOXY 1+(NR %6)*22, ROW+(NR/6)*9
   PRINT ALIGN$(MON$[NR], 21, 2);
   INCR ROW
   GOTOXY 1+(NR %6)*22, ROW+(NR/6)*9
   PRINT ALIGN$("MO TU WE TH FR SA SU", 21, 2);
   INCR ROW
   ' Each day
   FOR D = 1 TO MON[NR]
       ' Zeller
       J = VAL(LEFT$(Y$, 2))
       K = VAL(MID$(Y$, 3, 2))
       M = NR+1
       IF NR < 2 THEN
           INCR M, 12
           DECR K
       END IF
       H = (D + ((M+1)*26)/10 + K + (K/4) + (J/4) + 5*J)
       DAYNR = MOD(H, 7) - 2
       IF DAYNR < 0 THEN INCR DAYNR, 7
       IF DAYNR = 0 AND D > 1 THEN INCR ROW
       GOTOXY 1+(NR %6)*22+DAYNR*3, ROW+(NR/6)*9
       PRINT D;
   NEXT

NEXT</lang>

Output:
                                                           [SNOOPY HERE]                                                            
                                                                1969                                                                
       JANUARY              FEBRUARY                MARCH                 APRIL                  MAY                  JUNE         
MO TU WE TH FR SA SU  MO TU WE TH FR SA SU  MO TU WE TH FR SA SU  MO TU WE TH FR SA SU  MO TU WE TH FR SA SU  MO TU WE TH FR SA SU 
      1  2  3  4  5                  1  2                  1  2      1  2  3  4  5  6            1  2  3  4                     1
6  7  8  9  10 11 12  3  4  5  6  7  8  9   3  4  5  6  7  8  9   7  8  9  10 11 12 13  5  6  7  8  9  10 11  2  3  4  5  6  7  8
13 14 15 16 17 18 19  10 11 12 13 14 15 16  10 11 12 13 14 15 16  14 15 16 17 18 19 20  12 13 14 15 16 17 18  9  10 11 12 13 14 15
20 21 22 23 24 25 26  17 18 19 20 21 22 23  17 18 19 20 21 22 23  21 22 23 24 25 26 27  19 20 21 22 23 24 25  16 17 18 19 20 21 22
27 28 29 30 31        24 25 26 27 28        24 25 26 27 28 29 30  28 29 30              26 27 28 29 30 31     23 24 25 26 27 28 29
                                            31                                                                30

        JULY                 AUGUST               SEPTEMBER              OCTOBER              NOVEMBER              DECEMBER       
MO TU WE TH FR SA SU  MO TU WE TH FR SA SU  MO TU WE TH FR SA SU  MO TU WE TH FR SA SU  MO TU WE TH FR SA SU  MO TU WE TH FR SA SU 
   1  2  3  4  5  6               1  2  3   1  2  3  4  5  6  7         1  2  3  4  5                  1  2   1  2  3  4  5  6  7
7  8  9  10 11 12 13  4  5  6  7  8  9  10  8  9  10 11 12 13 14  6  7  8  9  10 11 12  3  4  5  6  7  8  9   8  9  10 11 12 13 14
14 15 16 17 18 19 20  11 12 13 14 15 16 17  15 16 17 18 19 20 21  13 14 15 16 17 18 19  10 11 12 13 14 15 16  15 16 17 18 19 20 21
21 22 23 24 25 26 27  18 19 20 21 22 23 24  22 23 24 25 26 27 28  20 21 22 23 24 25 26  17 18 19 20 21 22 23  22 23 24 25 26 27 28
28 29 30 31           25 26 27 28 29 30 31  29 30                 27 28 29 30 31        24 25 26 27 28 29 30  29 30 31

BBC BASIC

<lang bbcbasic> VDU 23,22,1056;336;8,16,16,128

     YEAR = 1969
     PRINT TAB(62) "[SNOOPY]" TAB(64); YEAR
     DIM DOM(5), MJD(5), DM(5), MONTH$(11)
     DAYS$ = "SU MO TU WE TH FR SA"
     MONTH$() = "JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUNE", \
     \ "JULY", "AUGUST", "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER"
     
     FOR MONTH = 1 TO 7 STEP 6
       PRINT
       FOR COL = 0 TO 5
         MJD(COL) = FNMJD(1, MONTH + COL, YEAR)
         MONTH$ = MONTH$(MONTH + COL - 1)
         PRINT TAB(COL*22 + 11 - LEN(MONTH$)/2) MONTH$;
       NEXT
       FOR COL = 0 TO 5
         PRINT TAB(COL*22 + 1) DAYS$;
         DM(COL) = FNDIM(MONTH + COL, YEAR)
       NEXT
       DOM() = 1
       COL = 0
       REPEAT
         DOW = FNDOW(MJD(COL))
         IF DOM(COL)<=DM(COL) THEN
           PRINT TAB(COL*22 + DOW*3 + 1); DOM(COL);
           DOM(COL) += 1
           MJD(COL) += 1
         ENDIF
         IF DOW=6 OR DOM(COL)>DM(COL) COL = (COL + 1) MOD 6
       UNTIL DOM(0)>DM(0) AND DOM(1)>DM(1) AND DOM(2)>DM(2) AND \
       \     DOM(3)>DM(3) AND DOM(4)>DM(4) AND DOM(5)>DM(5)
       PRINT
     NEXT
     END
     
     DEF FNMJD(D%,M%,Y%) : M% -= 3 : IF M% < 0 M% += 12 : Y% -= 1
     = D% + (153*M%+2)DIV5 + Y%*365 + Y%DIV4 - Y%DIV100 + Y%DIV400 - 678882
     
     DEF FNDOW(J%) = (J%+2400002) MOD 7
     
     DEF FNDIM(M%,Y%)
     CASE M% OF
       WHEN 2: = 28 - (Y%MOD4=0) + (Y%MOD100=0) - (Y%MOD400=0)
       WHEN 4,6,9,11: = 30
       OTHERWISE = 31
     ENDCASE</lang>
Output:
                                                              [SNOOPY]
                                                                1969

       JANUARY               FEBRUARY               MARCH                 APRIL                  MAY                   JUNE
 SU MO TU WE TH FR SA  SU MO TU WE TH FR SA  SU MO TU WE TH FR SA  SU MO TU WE TH FR SA  SU MO TU WE TH FR SA  SU MO TU WE TH FR SA
          1  2  3  4                     1                     1         1  2  3  4  5               1  2  3   1  2  3  4  5  6  7
 5  6  7  8  9  10 11  2  3  4  5  6  7  8   2  3  4  5  6  7  8   6  7  8  9  10 11 12  4  5  6  7  8  9  10  8  9  10 11 12 13 14
 12 13 14 15 16 17 18  9  10 11 12 13 14 15  9  10 11 12 13 14 15  13 14 15 16 17 18 19  11 12 13 14 15 16 17  15 16 17 18 19 20 21
 19 20 21 22 23 24 25  16 17 18 19 20 21 22  16 17 18 19 20 21 22  20 21 22 23 24 25 26  18 19 20 21 22 23 24  22 23 24 25 26 27 28
 26 27 28 29 30 31     23 24 25 26 27 28     23 24 25 26 27 28 29  27 28 29 30           25 26 27 28 29 30 31  29 30
                                             30 31

         JULY                 AUGUST              SEPTEMBER              OCTOBER               NOVEMBER              DECEMBER
 SU MO TU WE TH FR SA  SU MO TU WE TH FR SA  SU MO TU WE TH FR SA  SU MO TU WE TH FR SA  SU MO TU WE TH FR SA  SU MO TU WE TH FR SA
       1  2  3  4  5                  1  2      1  2  3  4  5  6            1  2  3  4                     1      1  2  3  4  5  6
 6  7  8  9  10 11 12  3  4  5  6  7  8  9   7  8  9  10 11 12 13  5  6  7  8  9  10 11  2  3  4  5  6  7  8   7  8  9  10 11 12 13
 13 14 15 16 17 18 19  10 11 12 13 14 15 16  14 15 16 17 18 19 20  12 13 14 15 16 17 18  9  10 11 12 13 14 15  14 15 16 17 18 19 20
 20 21 22 23 24 25 26  17 18 19 20 21 22 23  21 22 23 24 25 26 27  19 20 21 22 23 24 25  16 17 18 19 20 21 22  21 22 23 24 25 26 27
 27 28 29 30 31        24 25 26 27 28 29 30  28 29 30              26 27 28 29 30 31     23 24 25 26 27 28 29  28 29 30 31
                       31                                                                30

COBOL

Although it seems to be missing the pinup of Snoopy, see COBOL Calendar task entry where the code, and output, is already an example of a "REAL programmer" calendar; even down to the 6 character, all uppercase, program name CALEND.

Common Lisp

<lang lisp>(QL:QUICKLOAD '(DATE-CALC))

(DEFPARAMETER *DAY-ROW* "SU MO TU WE TH FR SA") (DEFPARAMETER *CALENDAR-MARGIN* 3)

(DEFUN MONTH-TO-WORD (MONTH)

 "TRANSLATE A MONTH FROM 1 TO 12 INTO ITS WORD REPRESENTATION."
 (SVREF #("JANUARY" "FEBRUARY" "MARCH" "APRIL"
          "MAY" "JUNE" "JULY" "AUGUST"
          "SEPTEMBER" "OCTOBER" "NOVEMBER" "DECEMBER")
        (1- MONTH)))

(DEFUN MONTH-STRINGS (YEAR MONTH)

 "COLLECT ALL OF THE STRINGS THAT MAKE UP A CALENDAR FOR A GIVEN

MONTH AND YEAR."

 `(,(DATE-CALC:CENTER (MONTH-TO-WORD MONTH) (LENGTH *DAY-ROW*))
    ,*DAY-ROW*
    ;; WE CAN ASSUME THAT A MONTH CALENDAR WILL ALWAYS FIT INTO A 7 BY 6 BLOCK
    ;; OF VALUES. THIS MAKES IT EASY TO FORMAT THE RESULTING STRINGS.
    ,@ (LET ((DAYS (MAKE-ARRAY (* 7 6) :INITIAL-ELEMENT NIL)))
         (LOOP :FOR I :FROM (DATE-CALC:DAY-OF-WEEK YEAR MONTH 1)
            :FOR DAY :FROM 1 :TO (DATE-CALC:DAYS-IN-MONTH YEAR MONTH)
            :DO (SETF (AREF DAYS I) DAY))
         (LOOP :FOR I :FROM 0 :TO 5
            :COLLECT
            (FORMAT NIL "~{~:[  ~;~2,D~]~^ ~}"
                    (LOOP :FOR DAY :ACROSS (SUBSEQ DAYS (* I 7) (+ 7 (* I 7)))
                       :APPEND (IF DAY (LIST DAY DAY) (LIST DAY))))))))

(DEFUN CALC-COLUMNS (CHARACTERS MARGIN-SIZE)

 "CALCULATE THE NUMBER OF COLUMNS GIVEN THE NUMBER OF CHARACTERS PER

COLUMN AND THE MARGIN-SIZE BETWEEN THEM."

 (MULTIPLE-VALUE-BIND (COLS EXCESS)
     (TRUNCATE CHARACTERS (+ MARGIN-SIZE (LENGTH *DAY-ROW*)))
   (INCF EXCESS MARGIN-SIZE)
   (IF (>= EXCESS (LENGTH *DAY-ROW*))
       (1+ COLS)
       COLS)))

(DEFUN TAKE (N LIST)

 "TAKE THE FIRST N ELEMENTS OF A LIST."
 (LOOP :REPEAT N :FOR X :IN LIST :COLLECT X))

(DEFUN DROP (N LIST)

 "DROP THE FIRST N ELEMENTS OF A LIST."
 (COND ((OR (<= N 0) (NULL LIST)) LIST)
       (T (DROP (1- N) (CDR LIST)))))

(DEFUN CHUNKS-OF (N LIST)

 "SPLIT THE LIST INTO CHUNKS OF SIZE N."
 (ASSERT (> N 0))
 (LOOP :FOR X := LIST :THEN (DROP N X)
    :WHILE X
    :COLLECT (TAKE N X)))

(DEFUN PRINT-CALENDAR (YEAR &KEY (CHARACTERS 80) (MARGIN-SIZE 3))

 "PRINT OUT THE CALENDAR FOR A GIVEN YEAR, OPTIONALLY SPECIFYING

A WIDTH LIMIT IN CHARACTERS AND MARGIN-SIZE BETWEEN MONTHS."

 (ASSERT (>= CHARACTERS (LENGTH *DAY-ROW*)))
 (ASSERT (>= MARGIN-SIZE 0))
 (LET* ((CALENDARS (LOOP :FOR MONTH :FROM 1 :TO 12
                      :COLLECT (MONTH-STRINGS YEAR MONTH)))
        (COLUMN-COUNT (CALC-COLUMNS CHARACTERS MARGIN-SIZE))
        (TOTAL-SIZE (+ (* COLUMN-COUNT (LENGTH *DAY-ROW*))
                       (* (1- COLUMN-COUNT) MARGIN-SIZE)))
        (FORMAT-STRING (CONCATENATE 'STRING
                                    "~{~A~^~" (WRITE-TO-STRING MARGIN-SIZE) ",0@T~}~%")))
   (FORMAT T "~A~%~A~%~%"
           (DATE-CALC:CENTER "[SNOOPY]" TOTAL-SIZE)
           (DATE-CALC:CENTER (WRITE-TO-STRING YEAR) TOTAL-SIZE))
   (LOOP :FOR ROW :IN (CHUNKS-OF COLUMN-COUNT CALENDARS)
      :DO (APPLY 'MAPCAR
                 (LAMBDA (&REST HEADS)
                   (FORMAT T FORMAT-STRING HEADS))
                 ROW))))</lang>
Output:
CL-USER> (PRINT-CALENDAR 1969)
                             [SNOOPY]                             
                               1969                               

      JANUARY                FEBRUARY                MARCH        
SU MO TU WE TH FR SA   SU MO TU WE TH FR SA   SU MO TU WE TH FR SA
          1  2  3  4                      1                      1
 5  6  7  8  9 10 11    2  3  4  5  6  7  8    2  3  4  5  6  7  8
12 13 14 15 16 17 18    9 10 11 12 13 14 15    9 10 11 12 13 14 15
19 20 21 22 23 24 25   16 17 18 19 20 21 22   16 17 18 19 20 21 22
26 27 28 29 30 31      23 24 25 26 27 28      23 24 25 26 27 28 29
                                              30 31               
       APRIL                   MAY                    JUNE        
SU MO TU WE TH FR SA   SU MO TU WE TH FR SA   SU MO TU WE TH FR SA
       1  2  3  4  5                1  2  3                       
 6  7  8  9 10 11 12    4  5  6  7  8  9 10    1  2  3  4  5  6  7
13 14 15 16 17 18 19   11 12 13 14 15 16 17    8  9 10 11 12 13 14
20 21 22 23 24 25 26   18 19 20 21 22 23 24   15 16 17 18 19 20 21
27 28 29 30            25 26 27 28 29 30 31   22 23 24 25 26 27 28
                                              29 30               
        JULY                  AUGUST               SEPTEMBER      
SU MO TU WE TH FR SA   SU MO TU WE TH FR SA   SU MO TU WE TH FR SA
       1  2  3  4  5                   1  2       1  2  3  4  5  6
 6  7  8  9 10 11 12    3  4  5  6  7  8  9    7  8  9 10 11 12 13
13 14 15 16 17 18 19   10 11 12 13 14 15 16   14 15 16 17 18 19 20
20 21 22 23 24 25 26   17 18 19 20 21 22 23   21 22 23 24 25 26 27
27 28 29 30 31         24 25 26 27 28 29 30   28 29 30            
                       31                                         
      OCTOBER                NOVEMBER               DECEMBER      
SU MO TU WE TH FR SA   SU MO TU WE TH FR SA   SU MO TU WE TH FR SA
          1  2  3  4                      1       1  2  3  4  5  6
 5  6  7  8  9 10 11    2  3  4  5  6  7  8    7  8  9 10 11 12 13
12 13 14 15 16 17 18    9 10 11 12 13 14 15   14 15 16 17 18 19 20
19 20 21 22 23 24 25   16 17 18 19 20 21 22   21 22 23 24 25 26 27
26 27 28 29 30 31      23 24 25 26 27 28 29   28 29 30 31         
                       30                                         
NIL

D

D keywords are lower case, so this silly solution uses the whole Calendar Task code, with small changes and all in upper case, in a text file named "CALENDAR":

IMPORT STD.STDIO, STD.DATETIME, STD.STRING, STD.CONV,
       STD.ALGORITHM, STD.ARRAY;

VOID PRINT_CALENDAR(IN UINT YEAR, IN UINT COLS)
IN {
    ASSERT(COLS > 0 && COLS <= 12);
} BODY {
    STATIC ENUM CAMEL_CASE = (STRING[] PARTS) PURE =>
        PARTS[0] ~ PARTS[1 .. $].MAP!CAPITALIZE.JOIN;

    IMMUTABLE ROWS = 12 / COLS + (12 % COLS != 0);
    MIXIN("AUTO DATE = " ~ "DATE(YEAR, 1, 1);".CAPITALIZE);
    ENUM STRING S1 = CAMEL_CASE("DAY OF WEEK".SPLIT);
    MIXIN(FORMAT("AUTO OFFS = CAST(INT)DATE.%S;", S1));
    CONST MONTHS = "JANUARY FEBRUARY MARCH APRIL MAY JUNE
        JULY AUGUST SEPTEMBER OCTOBER NOVEMBER DECEMBER"
        .SPLIT.MAP!CAPITALIZE.ARRAY;

    STRING[8][12] MONS;
    FOREACH (IMMUTABLE M; 0 .. 12) {
        MONS[M][0] = MONTHS[M].CENTER(21);
        MONS[M][1] = " " ~ "SU MO TU WE TH FR SA"
                           .SPLIT.MAP!CAPITALIZE.JOIN(" ");
        ENUM STRING S2 = CAMEL_CASE("DAYS IN MONTH".SPLIT);
        MIXIN(FORMAT("IMMUTABLE DIM = DATE.%S;", S2));
        FOREACH (IMMUTABLE D; 1 .. 43) {
            IMMUTABLE DAY = D > OFFS && D <= OFFS + DIM;
            IMMUTABLE STR = DAY ? FORMAT(" %2S", D-OFFS) : "   ";
            MONS[M][2 + (D - 1) / 7] ~= STR;
        }
        OFFS = (OFFS + DIM) % 7;
        DATE.ADD!"MONTHS"(1);
    }

    FORMAT("[%S %S]", "SNOOPY".CAPITALIZE, "PICTURE".CAPITALIZE)
    .CENTER(COLS * 24 + 4).WRITELN;
    WRITELN(YEAR.TEXT.CENTER(COLS * 24 + 4), "\N");
    FOREACH (IMMUTABLE R; 0 .. ROWS) {
        STRING[8] S;
        FOREACH (IMMUTABLE C; 0 .. COLS) {
            IF (R * COLS + C > 11)
                BREAK;
            FOREACH (IMMUTABLE I, LINE; MONS[R * COLS + C])
                S[I] ~= FORMAT("   %S", LINE);
        }
        WRITEFLN("%-(%S\N%)\N", S);
    }
}

STATIC THIS() {
    PRINT_CALENDAR(1969, 3);
}

Then in another source code file there is a little loader, that imports it and mixes-in it (for safety this program must be compiled with -Jsomepath): <lang d>import std.string;mixin(import("CALENDAR").toLower);void main(){}</lang>

Output:
                              [Snoopy Picture]                              
                                    1969                                    

          January                February                  March        
    Su Mo Tu We Th Fr Sa    Su Mo Tu We Th Fr Sa    Su Mo Tu We Th Fr Sa
              1  2  3  4                       1                       1
     5  6  7  8  9 10 11     2  3  4  5  6  7  8     2  3  4  5  6  7  8
    12 13 14 15 16 17 18     9 10 11 12 13 14 15     9 10 11 12 13 14 15
    19 20 21 22 23 24 25    16 17 18 19 20 21 22    16 17 18 19 20 21 22
    26 27 28 29 30 31       23 24 25 26 27 28       23 24 25 26 27 28 29
                                                    30 31               

           April                    May                    June         
    Su Mo Tu We Th Fr Sa    Su Mo Tu We Th Fr Sa    Su Mo Tu We Th Fr Sa
           1  2  3  4  5                 1  2  3     1  2  3  4  5  6  7
     6  7  8  9 10 11 12     4  5  6  7  8  9 10     8  9 10 11 12 13 14
    13 14 15 16 17 18 19    11 12 13 14 15 16 17    15 16 17 18 19 20 21
    20 21 22 23 24 25 26    18 19 20 21 22 23 24    22 23 24 25 26 27 28
    27 28 29 30             25 26 27 28 29 30 31    29 30               
                                                                        

           July                   August                 September      
    Su Mo Tu We Th Fr Sa    Su Mo Tu We Th Fr Sa    Su Mo Tu We Th Fr Sa
           1  2  3  4  5                    1  2        1  2  3  4  5  6
     6  7  8  9 10 11 12     3  4  5  6  7  8  9     7  8  9 10 11 12 13
    13 14 15 16 17 18 19    10 11 12 13 14 15 16    14 15 16 17 18 19 20
    20 21 22 23 24 25 26    17 18 19 20 21 22 23    21 22 23 24 25 26 27
    27 28 29 30 31          24 25 26 27 28 29 30    28 29 30            
                            31                                          

          October                November                December       
    Su Mo Tu We Th Fr Sa    Su Mo Tu We Th Fr Sa    Su Mo Tu We Th Fr Sa
              1  2  3  4                       1        1  2  3  4  5  6
     5  6  7  8  9 10 11     2  3  4  5  6  7  8     7  8  9 10 11 12 13
    12 13 14 15 16 17 18     9 10 11 12 13 14 15    14 15 16 17 18 19 20
    19 20 21 22 23 24 25    16 17 18 19 20 21 22    21 22 23 24 25 26 27
    26 27 28 29 30 31       23 24 25 26 27 28 29    28 29 30 31         
                            30       

GUISS

In Graphical User Interface Support Script, we utilize applications that are already written. So for this task, we shall just display the calendar that sets the system clock.

<lang guiss>RIGHTCLICK:CLOCK,ADJUST DATE AND TIME,BUTTON:CANCEL</lang>

Elena

ELENA 3.4 : <lang elena>import system'text. import system'routines. import system'calendar. import extensions. import extensions'routines.

const MonthNames = ("JANUARY","FEBRUARY","MARCH","APRIL","MAY","JUNE","JULY","AUGUST","SEPTEMBER","OCTOBER","NOVEMBER","DECEMBER"). const DayNames = ("MO", "TU", "WE", "TH", "FR", "SA", "SU").

class CalendarMonthPrinter {

   object theDate.
   object theLine.
   object theMonth.
   object theYear.
   object theRow.
   
   constructor year:aYear month:aMonth
   [
       theMonth := aMonth.
       theYear := aYear.
       theLine := TextBuilder new.
       theRow := Integer new(0).
   ]
   writeTitle
   [        
       theRow value := 0.
       theDate := Date new(theYear, theMonth, 1).
       DayNames forEach(:aName)
           [ theLine print(" ",aName) ]
   ]
   
   writeLine
   [
       theLine clear.
       
       if (theDate month == theMonth)
           [
               theLine write:"   " length((theDate dayOfWeek == 0)iif(7,theDate dayOfWeek) - 1).
               
               [
                   theLine write:(theDate day; literal) paddingLeft:3 with:$32.                    
                   theDate := theDate addDays:1.
               ]         
               repeatUntil:$((theDate month != theMonth)||(theDate dayOfWeek == 1)).
           ].
       
       int aLength := theLine length.
       if (aLength < 21)
           [ theLine write:" " length(21 - aLength). ].
           
       theRow append(1).            
   ]
   
   indexer = BaseIndexer::
   {
       bool available = theRow < 7.
       readIndexTo(ref<int> anIndex) [ theRow readValueTo(anIndex) ]
       writeIndex(int anIndex)
       [
           if (anIndex <= theRow)
               [ self writeTitle ].
               
           while (anIndex > theRow)
               [ self writeLine ]
       ]
       appendIndex(int anIndex)
           <= writeIndex(theRow value + anIndex).
       
       readLengthTo(ref<int> retVal) [ retVal value := 7 ]
       get = self.
       
       set : o [ NotSupportedException new; raise ]
   }.
   
   printTitleTo : anOutput
   [
       anOutput write(MonthNames[theMonth - 1]) padding:21 with:$32.
   ]
  
   printTo : anOutput
   [
       anOutput write(theLine literal).
   ]

}

class Calendar {

   int theYear.
   int theRowLength.
   
   constructor new : aYear
   [
       theYear := aYear.
       theRowLength := 3.
   ]
   
   printTo:anOutput
   [
       anOutput write:"[SNOOPY]" padding:(theRowLength * 25) with:$32. 
       anOutput writeLine.        
       anOutput write:(theYear literal) padding:(theRowLength * 25) with:$32. 
       anOutput writeLine; writeLine.
       
       var aRowCount := 12 / theRowLength.
       var Months := Array new(aRowCount); populate(:i)
           (Array new:theRowLength; 
               populate(:j)
                   ( CalendarMonthPrinter year:theYear month(i * theRowLength + j + 1))).
       
       Months forEach(:aRow)
       [
           aRow forEach(:aMonth)
           [
               aMonth printTitleTo:anOutput.                    
               anOutput write:"   ".
           ].
           
           anOutput writeLine.
           
           ParallelEnumerator new:aRow; forEach(:aLine)
           [
               aLine forEach(:aPrinter)
               [
                   aPrinter printTo:anOutput.
                   anOutput write:"   "
               ].
               anOutput writeLine
           ].
       ].        
   ]

}

public program = [

   var aCalender := Calendar new(console write:"ENTER THE YEAR:"; readLineTo(Integer new)).
   
   aCalender printTo:console.
   
   console readChar.

].</lang>

Output:
ENTER THE YEAR:1969
                                 [SNOOPY]
                                   1969

       JANUARY                FEBRUARY                  MARCH
 MO TU WE TH FR SA SU    MO TU WE TH FR SA SU    MO TU WE TH FR SA SU
        1  2  3  4  5                    1  2                    1  2
  6  7  8  9 10 11 12     3  4  5  6  7  8  9     3  4  5  6  7  8  9
 13 14 15 16 17 18 19    10 11 12 13 14 15 16    10 11 12 13 14 15 16
 20 21 22 23 24 25 26    17 18 19 20 21 22 23    17 18 19 20 21 22 23
 27 28 29 30 31          24 25 26 27 28          24 25 26 27 28 29 30
                                                 31
        APRIL                    MAY                    JUNE
 MO TU WE TH FR SA SU    MO TU WE TH FR SA SU    MO TU WE TH FR SA SU
     1  2  3  4  5  6              1  2  3  4                       1
  7  8  9 10 11 12 13     5  6  7  8  9 10 11     2  3  4  5  6  7  8
 14 15 16 17 18 19 20    12 13 14 15 16 17 18     9 10 11 12 13 14 15
 21 22 23 24 25 26 27    19 20 21 22 23 24 25    16 17 18 19 20 21 22
 28 29 30                26 27 28 29 30 31       23 24 25 26 27 28 29
                                                 30
        JULY                   AUGUST                 SEPTEMBER
 MO TU WE TH FR SA SU    MO TU WE TH FR SA SU    MO TU WE TH FR SA SU
     1  2  3  4  5  6                 1  2  3     1  2  3  4  5  6  7
  7  8  9 10 11 12 13     4  5  6  7  8  9 10     8  9 10 11 12 13 14
 14 15 16 17 18 19 20    11 12 13 14 15 16 17    15 16 17 18 19 20 21
 21 22 23 24 25 26 27    18 19 20 21 22 23 24    22 23 24 25 26 27 28
 28 29 30 31             25 26 27 28 29 30 31    29 30

       OCTOBER                NOVEMBER                DECEMBER
 MO TU WE TH FR SA SU    MO TU WE TH FR SA SU    MO TU WE TH FR SA SU
        1  2  3  4  5                    1  2     1  2  3  4  5  6  7
  6  7  8  9 10 11 12     3  4  5  6  7  8  9     8  9 10 11 12 13 14
 13 14 15 16 17 18 19    10 11 12 13 14 15 16    15 16 17 18 19 20 21
 20 21 22 23 24 25 26    17 18 19 20 21 22 23    22 23 24 25 26 27 28
 27 28 29 30 31          24 25 26 27 28 29 30    29 30 31

Fortran

Alas, the header "FORTRAN" is not recognised - REAL programmers were absent that day? Even upon the apperance of lower case, I have preferred to use shouting for programme source, and normal upper/lower case for commentary. Aside from petty details such as 1 and l being nowhere as distinct as 1 and L, this allows the two sorts of blather to be identifiably different without ratiocination as the hours drag past. Further, the names of variables can easily be distinguished from the same word in discussion, as in ... the text in TEXT will be printed as the subtitle to the text in TITLE ... Anyway, in the spirit of old, herewith the source without tedious commentary: <lang FORTRAN>

      MODULE DATEGNASH
      TYPE DATEBAG
       INTEGER DAY,MONTH,YEAR
      END TYPE DATEBAG
      CHARACTER*9 MONTHNAME(12),DAYNAME(0:6)
      PARAMETER (MONTHNAME = (/"JANUARY","FEBRUARY","MARCH","APRIL",
    1  "MAY","JUNE","JULY","AUGUST","SEPTEMBER","OCTOBER","NOVEMBER",
    2  "DECEMBER"/))
      PARAMETER (DAYNAME = (/"SUNDAY","MONDAY","TUESDAY","WEDNESDAY",
    1  "THURSDAY","FRIDAY","SATURDAY"/))
      INTEGER*4 JDAYSHIFT
      PARAMETER (JDAYSHIFT = 2415020)
      CONTAINS
      INTEGER FUNCTION LSTNB(TEXT)
       CHARACTER*(*),INTENT(IN):: TEXT
       INTEGER L
        L = LEN(TEXT)
   1    IF (L.LE.0) GO TO 2
        IF (ICHAR(TEXT(L:L)).GT.ICHAR(" ")) GO TO 2
        L = L - 1
        GO TO 1
   2    LSTNB = L
       RETURN
      END FUNCTION LSTNB
     CHARACTER*2 FUNCTION I2FMT(N)
      INTEGER*4 N
       IF (N.LT.0) THEN
         IF (N.LT.-9) THEN
           I2FMT = "-!"
          ELSE
           I2FMT = "-"//CHAR(ICHAR("0") - N)
         END IF
       ELSE IF (N.LT.10) THEN
         I2FMT = " " //CHAR(ICHAR("0") + N)
       ELSE IF (N.LT.100) THEN
         I2FMT = CHAR(N/10      + ICHAR("0"))
    1           //CHAR(MOD(N,10) + ICHAR("0"))
       ELSE
         I2FMT = "+!"
       END IF
     END FUNCTION I2FMT
     CHARACTER*8 FUNCTION I8FMT(N)
      INTEGER*4 N
      CHARACTER*8 HIC
       WRITE (HIC,1) N
   1   FORMAT (I8)
       I8FMT = HIC
     END FUNCTION I8FMT
     SUBROUTINE SAY(OUT,TEXT)
      INTEGER OUT
      CHARACTER*(*) TEXT
       WRITE (6,1) TEXT(1:LSTNB(TEXT))
   1   FORMAT (A)
     END SUBROUTINE SAY
      INTEGER*4 FUNCTION DAYNUM(YY,M,D)
       INTEGER*4 JDAYN
       INTEGER YY,Y,M,MM,D
        Y = YY
        IF (Y.LT.1) Y = Y + 1
        MM = (M - 14)/12
        JDAYN = D - 32075
    A    + 1461*(Y + 4800  + MM)/4
    B    +  367*(M - 2     - MM*12)/12
    C    -    3*((Y + 4900 + MM)/100)/4
        DAYNUM = JDAYN - JDAYSHIFT
      END FUNCTION DAYNUM
      TYPE(DATEBAG) FUNCTION MUNYAD(DAYNUM)
       INTEGER*4 DAYNUM,JDAYN
       INTEGER Y,M,D,L,N
        JDAYN = DAYNUM + JDAYSHIFT
        L = JDAYN + 68569
        N = 4*L/146097
        L = L - (146097*N + 3)/4
        Y = 4000*(L + 1)/1461001
        L = L - 1461*Y/4 + 31
        M = 80*L/2447
        D = L - 2447*M/80
        L = M/11
        M = M + 2 - 12*L
        Y = 100*(N - 49) + Y + L
        IF (Y.LT.1) Y = Y - 1
        MUNYAD%YEAR  = Y
        MUNYAD%MONTH = M
        MUNYAD%DAY   = D
      END FUNCTION MUNYAD
      INTEGER FUNCTION PMOD(N,M)
       INTEGER N,M
        PMOD = MOD(MOD(N,M) + M,M)
      END FUNCTION PMOD
     SUBROUTINE CALENDAR(Y1,Y2,COLUMNS)
      INTEGER Y1,Y2,YEAR
      INTEGER M,M1,M2,MONTH
      INTEGER*4 DN1,DN2,DN,D
      INTEGER W,G
      INTEGER L,LINE
      INTEGER COL,COLUMNS,COLWIDTH
      CHARACTER*200 STRIPE(6),SPECIAL(6),MLINE,DLINE
       W = 3
       G = 1
       COLWIDTH = 7*W + G
     Y:DO YEAR = Y1,Y2
         CALL SAY(MSG,"")
         IF (YEAR.EQ.0) THEN
           CALL SAY(MSG,"THERE IS NO YEAR ZERO.")
           CYCLE Y
         END IF
         MLINE = ""
         L = (COLUMNS*COLWIDTH - G - 8)/2
         IF (YEAR.GT.0) THEN
           MLINE(L:) = I8FMT(YEAR)
          ELSE
           MLINE(L - 1:) = I8FMT(-YEAR)//"BC"
         END IF
         CALL SAY(MSG,MLINE)
         DO MONTH = 1,12,COLUMNS
           M1 = MONTH
           M2 = MIN(12,M1 + COLUMNS - 1)
           MLINE = ""
           DLINE = ""
           STRIPE = ""
           SPECIAL = ""
           L0 = 1
           DO M = M1,M2
             L = (COLWIDTH - G - LSTNB(MONTHNAME(M)))/2 - 1
             MLINE(L0 + L:) = MONTHNAME(M)
             DO D = 0,6
               L = L0 + (3 - W) + D*W
               DLINE(L:L + 2) = DAYNAME(D)(1:W - 1)
             END DO
             DN1 = DAYNUM(YEAR,M,1)
             DN2 = DAYNUM(YEAR,M + 1,0)
             COL = MOD(PMOD(DN1,7) + 7,7)
             LINE = 1
             D = 1
             DO DN = DN1,DN2
               L = L0 + COL*W
               STRIPE(LINE)(L:L + 1) = I2FMT(D)
               D = D + 1
               COL = COL + 1
               IF (COL.GT.6) THEN
                 LINE = LINE + 1
                 COL = 0
               END IF
             END DO
             L0 = L0 + 7*W + G
           END DO
           CALL SAY(MSG,MLINE)
           CALL SAY(MSG,DLINE)
           DO LINE = 1,6
             IF (STRIPE(LINE).NE."") THEN
               CALL SAY(MSG,STRIPE(LINE))
             END IF
           END DO
         END DO
       END DO Y
       CALL SAY(MSG,"")
     END SUBROUTINE CALENDAR
     END MODULE DATEGNASH
     PROGRAM SHOW1968
      USE DATEGNASH
      INTEGER NCOL
       DO NCOL = 1,6
         CALL CALENDAR(1969,1969,NCOL)
       END DO
     END

</lang>

And for output, the wide form:

                                                                1969
      JANUARY              FEBRUARY                MARCH                 APRIL                  MAY                  JUNE
SU MO TU WE TH FR SA  SU MO TU WE TH FR SA  SU MO TU WE TH FR SA  SU MO TU WE TH FR SA  SU MO TU WE TH FR SA  SU MO TU WE TH FR SA
          1  2  3  4                     1                     1         1  2  3  4  5               1  2  3   1  2  3  4  5  6  7
 5  6  7  8  9 10 11   2  3  4  5  6  7  8   2  3  4  5  6  7  8   6  7  8  9 10 11 12   4  5  6  7  8  9 10   8  9 10 11 12 13 14
12 13 14 15 16 17 18   9 10 11 12 13 14 15   9 10 11 12 13 14 15  13 14 15 16 17 18 19  11 12 13 14 15 16 17  15 16 17 18 19 20 21
19 20 21 22 23 24 25  16 17 18 19 20 21 22  16 17 18 19 20 21 22  20 21 22 23 24 25 26  18 19 20 21 22 23 24  22 23 24 25 26 27 28
26 27 28 29 30 31     23 24 25 26 27 28     23 24 25 26 27 28 29  27 28 29 30           25 26 27 28 29 30 31  29 30
                                            30 31
       JULY                 AUGUST               SEPTEMBER              OCTOBER              NOVEMBER              DECEMBER
SU MO TU WE TH FR SA  SU MO TU WE TH FR SA  SU MO TU WE TH FR SA  SU MO TU WE TH FR SA  SU MO TU WE TH FR SA  SU MO TU WE TH FR SA
       1  2  3  4  5                  1  2      1  2  3  4  5  6            1  2  3  4                     1      1  2  3  4  5  6
 6  7  8  9 10 11 12   3  4  5  6  7  8  9   7  8  9 10 11 12 13   5  6  7  8  9 10 11   2  3  4  5  6  7  8   7  8  9 10 11 12 13
13 14 15 16 17 18 19  10 11 12 13 14 15 16  14 15 16 17 18 19 20  12 13 14 15 16 17 18   9 10 11 12 13 14 15  14 15 16 17 18 19 20
20 21 22 23 24 25 26  17 18 19 20 21 22 23  21 22 23 24 25 26 27  19 20 21 22 23 24 25  16 17 18 19 20 21 22  21 22 23 24 25 26 27
27 28 29 30 31        24 25 26 27 28 29 30  28 29 30              26 27 28 29 30 31     23 24 25 26 27 28 29  28 29 30 31
                      31                                                                30

Actual lineprinters offer the opportunity of overprinting lines so double (or triple) printing of the same text gave a bold effect if with some blurring due to wobble. Further decoration was possible: via underlines (and for overlines, an underline on the previous line) the appearance can be improved. Vertical bars can also be used, and more advanced lineprinters (IBM1403 etc. using the "TN" chain) or dot-matrix printers also supplied "corner" glyphs so that boxes would not have leaks.

FreeBASIC

<lang freebasic>' VERSION 16-03-2016 ' COMPILE WITH: FBC -S CONSOLE

' TRUE/FALSE ARE BUILT-IN CONSTANTS SINCE FREEBASIC 1.04 ' BUT WE HAVE TO DEFINE THEM FOR OLDER VERSIONS.

  1. IFNDEF TRUE
   #DEFINE FALSE 0
   #DEFINE TRUE NOT FALSE
  1. ENDIF

FUNCTION WD(M AS INTEGER, D AS INTEGER, Y AS INTEGER) AS INTEGER

   ' ZELLERISH
   ' 0 = SUNDAY, 1 = MONDAY, 2 = TUESDAY, 3 = WEDNESDAY
   ' 4 = THURSDAY, 5 = FRIDAY, 6 = SATURDAY
   IF M < 3 THEN        ' IF M = 1 OR M = 2 THEN
       M += 12
       Y -= 1
   END IF
   RETURN (Y + (Y \ 4) - (Y \ 100) + (Y \ 400) + D + ((153 * M + 8) \ 5)) MOD 7

END FUNCTION

FUNCTION LEAPYEAR(Y AS INTEGER) AS INTEGER

   IF (Y MOD 4) <> 0 THEN RETURN FALSE
   IF (Y MOD 100) = 0 ANDALSO (Y MOD 400) <> 0 THEN RETURN FALSE
   RETURN TRUE

END FUNCTION

' ------=< MAIN >=------ ' HARD CODED FOR 132 CHARACTERS PER LINE

DIM AS STRING WDN = "MO TU WE TH FR SA SU" ' WEEKDAY NAMES DIM AS STRING MO(1 TO 12) => {"JANUARY", "FEBRUARY", "MARCH", "APRIL", _

                        "MAY", "JUNE", "JULY", "AUGUST", "SEPTEMBER", _
                                   "OCTOBER", "NOVEMBER", "DECEMBER"}

DIM AS STRING TMP1, TMP2, D(1 TO 12)

DIM AS UINTEGER ML(1 TO 12) => {31,28,31,30,31,30,31,31,30,31,30,31} DIM AS UINTEGER I, I1, J, K, Y = 1969

'SCREENRES 1080,600,8

IF LEAPYEAR(Y) = TRUE THEN ML(2) = 29

TMP1 = "" FOR I = 1 TO 31

   TMP1 = TMP1 + RIGHT(("  " + STR(I)), 3)

NEXT I


FOR I = 1 TO 12

   TMP2 = ""
   J = WD(I,1, Y)
   IF J = 0 THEN J = 7
   J = J - 1
   TMP2 = SPACE(J * 3) + LEFT(TMP1, ML(I) * 3) + SPACE(21)
   D(I) = TMP2

NEXT I

PRINT TMP1 = "INSERT YOUR SNOOPY PICTURE HERE" PRINT SPACE((132 - LEN(TMP1)) \ 2); TMP1 PRINT TMP1 = STR(Y) PRINT SPACE((132 - LEN(TMP1)) \ 2); TMP1 PRINT

' 6 MONTH ON A ROW TMP2 = " " FOR I = 1 TO 6

   TMP2 = TMP2 + WDN
   IF I < 6 THEN TMP2 = TMP2 + "  "

NEXT I

FOR I = 1 TO 12 STEP 6

   TMP1 = ""
   FOR J = I TO I + 4
       TMP1 = TMP1 + LEFT(SPACE((22 - LEN(MO(J))) \ 2) + MO(J) + SPACE(11), 22)
   NEXT J
   TMP1 = TMP1 + SPACE((22 - LEN(MO(I + 5))) \ 2) + MO(I + 5)
   PRINT TMP1
   PRINT TMP2
   FOR J = 1 TO 85 STEP 21
       FOR K = I TO I + 4
           PRINT MID(D(K), J ,21); " ";
       NEXT K
       PRINT MID(D(I + 5), J ,21)
   NEXT J
   PRINT

NEXT I

' EMPTY KEYBOARD BUFFER WHILE INKEY <> "" : WEND PRINT : PRINT "HIT ANY KEY TO END PROGRAM" SLEEP END</lang>

Output:
                                                  INSERT YOUR SNOOPY PICTURE HERE

                                                                1969

       JANUARY               FEBRUARY               MARCH                 APRIL                  MAY                   JUNE
 MO TU WE TH FR SA SU  MO TU WE TH FR SA SU  MO TU WE TH FR SA SU  MO TU WE TH FR SA SU  MO TU WE TH FR SA SU  MO TU WE TH FR SA SU
        1  2  3  4  5                  1  2                  1  2      1  2  3  4  5  6            1  2  3  4                     1
  6  7  8  9 10 11 12   3  4  5  6  7  8  9   3  4  5  6  7  8  9   7  8  9 10 11 12 13   5  6  7  8  9 10 11   2  3  4  5  6  7  8
 13 14 15 16 17 18 19  10 11 12 13 14 15 16  10 11 12 13 14 15 16  14 15 16 17 18 19 20  12 13 14 15 16 17 18   9 10 11 12 13 14 15
 20 21 22 23 24 25 26  17 18 19 20 21 22 23  17 18 19 20 21 22 23  21 22 23 24 25 26 27  19 20 21 22 23 24 25  16 17 18 19 20 21 22
 27 28 29 30 31        24 25 26 27 28        24 25 26 27 28 29 30  28 29 30              26 27 28 29 30 31     23 24 25 26 27 28 29

         JULY                 AUGUST              SEPTEMBER              OCTOBER               NOVEMBER              DECEMBER
 MO TU WE TH FR SA SU  MO TU WE TH FR SA SU  MO TU WE TH FR SA SU  MO TU WE TH FR SA SU  MO TU WE TH FR SA SU  MO TU WE TH FR SA SU
     1  2  3  4  5  6               1  2  3   1  2  3  4  5  6  7         1  2  3  4  5                  1  2   1  2  3  4  5  6  7
  7  8  9 10 11 12 13   4  5  6  7  8  9 10   8  9 10 11 12 13 14   6  7  8  9 10 11 12   3  4  5  6  7  8  9   8  9 10 11 12 13 14
 14 15 16 17 18 19 20  11 12 13 14 15 16 17  15 16 17 18 19 20 21  13 14 15 16 17 18 19  10 11 12 13 14 15 16  15 16 17 18 19 20 21
 21 22 23 24 25 26 27  18 19 20 21 22 23 24  22 23 24 25 26 27 28  20 21 22 23 24 25 26  17 18 19 20 21 22 23  22 23 24 25 26 27 28
 28 29 30 31           25 26 27 28 29 30 31  29 30                 27 28 29 30 31        24 25 26 27 28 29 30  29 30 31            

Icon and Unicon

Icon and Unicon don't lend themselves to REAL programming in the sense of this task easily. And initially this task was marked omit because the primary declarations, reserved words, and the name of the main procedure are all in lowercase. However, getting in the spirit of the task real programmers do not give up and a number of solutions are possible:

  • A real programmer could write a preprocessor to eliminate lower case or insert before translation the one unreal line needed to realize this solution
  • An uber-real programmer would rewrite the entire translator
  • Or, a real programmer could do what's presented below on a coffee break with the preprocessor

In the example,

  • we must concede lowercase letters for the preprocessor directive $include (although as noted a preprocessor could handle this)
  • we temporarily concede the lowercase letters needed to realize the IPL procedures IsLeapYear and julian; however, a real programmer could easily rewrite these in a more real format (or an uber-real programmer would just rewrite the IPL
  • the character set usage has been reduced from 69 unique characters to 51 (within 6 bit character representations) by the following tactics:
    • elimination of # and all comments as real programmers don't need them
    • use of preprocessor definitions to eliminate the need for {[]}
    • use of char (excuse me CHAR) to generate characters such as "\n"
    • elimination of tabs for blanks

Now clearly all of these measures will make the storage, interpretation, and comprehension of this program more real and efficient for real programmers like us.

Oh, dear. It seems I have written documentation to explain what I have done. Tisk. Tisk. Someone come take my real programmer epaulettes away. And, you! Since you've read this you must surrender your stripes too.

Also it makes me go all nostalgic for my old WATFIVE compiler. And an IBM 129 keypunch. And 5 hole paper tape.

<lang Unicon>$include "REALIZE.ICN"

LINK DATETIME $define ISLEAPYEAR IsLeapYear $define JULIAN julian

PROCEDURE MAIN(A)

  PRINTCALENDAR(\A$<1$>|1969)	

END

PROCEDURE PRINTCALENDAR(YEAR)

  COLS := 3                                        
  MONS := $<$>                                       
  "JANUARY FEBRUARY MARCH APRIL MAY JUNE " || 
  "JULY AUGUST SEPTEMBER OCTOBER NOVEMBER DECEMBER " ?
         WHILE PUT(MONS, TAB(FIND(" "))) DO MOVE(1)    
  WRITE(CENTER("$<SNOOPY PICTURE$>",COLS * 24 + 4))  
  WRITE(CENTER(YEAR,COLS * 24 + 4), CHAR(10))          
  
  M := LIST(COLS)	                                        
  EVERY  MON := 0 TO 9 BY COLS DO $(               
     WRITES("    ")
     EVERY I := 1 TO COLS DO {
        WRITES(CENTER(MONS$<MON+I$>,24))             
        M$<I$> := CREATE CALENDARFORMATWEEK(YEAR,MON + I)  
        $)
     WRITE()
     EVERY 1 TO 7 DO $(                                      
        EVERY C := 1 TO COLS DO $(                 
           WRITES("    ")
           EVERY 1 TO 7 DO WRITES(RIGHT(@M$<C$>,3))  
           $)
        WRITE()
        $)
     $)
  RETURN

END

PROCEDURE CALENDARFORMATWEEK(YEAR,M)

  STATIC D
  INITIAL D := $<31,28,31,30,31,30,31,31,30,31,30,31$>  
  EVERY SUSPEND "SU"|"MO"|"TU"|"WE"|"TH"|"FR"|"SA"          
  EVERY 1 TO (DAY := (JULIAN(M,1,YEAR)+1)%7) DO SUSPEND ""    
  EVERY SUSPEND 1 TO D$<M$> DO DAY +:= 1                        
  IF M = 2 & ISLEAPYEAR(YEAR) THEN SUSPEND (DAY +:= 1, 29)    
  EVERY DAY TO (6*7) DO SUSPEND ""                            

END</lang>

Where REALIZE.ICN would be something like this (this example is incomplete but sufficient for this program):

<lang Icon>$define PROCEDURE procedure $define END end $define WRITE write $define WRITES writes $define SUSPEND suspend $define DO do $define TO to $define EVERY every $define LIST list $define WHILE while $define MAIN main $define PUT put $define TAB tab $define MOVE move $define CHAR move $define CENTER center $define RIGHT right $define FIND find $define STATIC static $define INITIAL initial $define CREATE create $define LINK link $define IF if $define THEN then $define BY by $define DATETIME datetime $define RETURN return</lang>

DATETIME.ICN provides IsLeapYear and julian

J

For added "real"ness, we also only use 1 character names:

<lang J>B=: + 4 100 400 -/@:<.@:%~ <: M=: 28+ 3, (10$5$3 2),~ 0 ~:/@:= 4 100 400 | ] R=: (7 -@| B+ 0, +/\@}:@M) |."0 1 (0,#\#~41) (]&:>: *"1 >/)~ M H=. _3(_11&{.)\'JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC' H=. 'SU MO TU WE TH FR SA',:"1~H C=: H <@,"(2) 12 6 21 }."1@($,) (' ',3 ":,.#\#~31) {~ R D=: 0 ": -@<.@%&21@+&1@[ ]\ C@] L=: |."0 1~ +/ .(*./\@:=)"1&' ' E=: (|."0 1~ _2 <.@%~ +/ .(*./\.@:=)"1&' ')@:({."1) L F=: 0 _1 }. 0 1 }. (2+[) E '[INSERT SNOOPY HERE]', ":@], D</lang>

B: given a year returns a number which when added to numeric values indexing days that year, mod 7, index the proper day names within a week. (In other words 7 | 0 + B 1969 gives the day of week index for the first day of 1969.)

M: given a year return a list of 12 numbers representing the number of days in each month

R: given a year, return 12 rows of 42 numbers, each row representing days of the month framed in a six week period which will be used to display that month (0 for days that are not part of that month)

H: text that will be the header for each month's block of days

C: A calendar of 12 months (in a flat list, each month is organized text but the months are not yet arranged).

D: given a number of characters (at least 20) and a year, gives the calendar arranged in rows that will best fill that character width without exceeding it.

L: given a textual table (fixed width character columns), left justify it

E: given a textual table and a width, center the text within that width (assuming it fits)

F: width F year gives us our formatted calendar. We do a little extra work here to make sure that a 20 character wide calendar can be displayed. (In that case, we trim off the left and right borders. We use the same trimming code in all cases, but typically we trim empty space added specially for this purpose. That said, the 20 character wide thing seems to be gone from the task description so this definition should be simplified...)

Here's an example calendar (the first line 132 F 1969 being the command that build this calendar):

<lang> 132 F 1969

                                                       [INSERT SNOOPY HERE]                                                        
                                                               1969                                                                
  ┌────────────────────┬────────────────────┬────────────────────┬────────────────────┬────────────────────┬────────────────────┐  
  │        JAN         │        FEB         │        MAR         │        APR         │        MAY         │        JUN         │  
  │SU MO TU WE TH FR SA│SU MO TU WE TH FR SA│SU MO TU WE TH FR SA│SU MO TU WE TH FR SA│SU MO TU WE TH FR SA│SU MO TU WE TH FR SA│  
  │          1  2  3  4│                   1│                   1│       1  2  3  4  5│             1  2  3│ 1  2  3  4  5  6  7│  
  │ 5  6  7  8  9 10 11│ 2  3  4  5  6  7  8│ 2  3  4  5  6  7  8│ 6  7  8  9 10 11 12│ 4  5  6  7  8  9 10│ 8  9 10 11 12 13 14│  
  │12 13 14 15 16 17 18│ 9 10 11 12 13 14 15│ 9 10 11 12 13 14 15│13 14 15 16 17 18 19│11 12 13 14 15 16 17│15 16 17 18 19 20 21│  
  │19 20 21 22 23 24 25│16 17 18 19 20 21 22│16 17 18 19 20 21 22│20 21 22 23 24 25 26│18 19 20 21 22 23 24│22 23 24 25 26 27 28│  
  │26 27 28 29 30 31   │23 24 25 26 27 28   │23 24 25 26 27 28 29│27 28 29 30         │25 26 27 28 29 30 31│29 30               │  
  │                    │                    │30 31               │                    │                    │                    │  
  ├────────────────────┼────────────────────┼────────────────────┼────────────────────┼────────────────────┼────────────────────┤  
  │        JUL         │        AUG         │        SEP         │        OCT         │        NOV         │        DEC         │  
  │SU MO TU WE TH FR SA│SU MO TU WE TH FR SA│SU MO TU WE TH FR SA│SU MO TU WE TH FR SA│SU MO TU WE TH FR SA│SU MO TU WE TH FR SA│  
  │       1  2  3  4  5│                1  2│    1  2  3  4  5  6│          1  2  3  4│                   1│    1  2  3  4  5  6│  
  │ 6  7  8  9 10 11 12│ 3  4  5  6  7  8  9│ 7  8  9 10 11 12 13│ 5  6  7  8  9 10 11│ 2  3  4  5  6  7  8│ 7  8  9 10 11 12 13│  
  │13 14 15 16 17 18 19│10 11 12 13 14 15 16│14 15 16 17 18 19 20│12 13 14 15 16 17 18│ 9 10 11 12 13 14 15│14 15 16 17 18 19 20│  
  │20 21 22 23 24 25 26│17 18 19 20 21 22 23│21 22 23 24 25 26 27│19 20 21 22 23 24 25│16 17 18 19 20 21 22│21 22 23 24 25 26 27│  
  │27 28 29 30 31      │24 25 26 27 28 29 30│28 29 30            │26 27 28 29 30 31   │23 24 25 26 27 28 29│28 29 30 31         │  
  │                    │31                  │                    │                    │30                  │                    │  
  └────────────────────┴────────────────────┴────────────────────┴────────────────────┴────────────────────┴────────────────────┘  

</lang>

Note that this version of F will work fine with a left argument of 20 (why anyone felt that this was important to mention is perhaps best thought of as an issue lost in history).

Kotlin

Kotlin is case-sensitive: all its keywords and packages are lower case, all its library classes are mixed case and its library functions are either lower case or mixed case. Consequently, it is impossible to run an upper case version of the Calendar task program as it stands. So what I've done instead (and similar to what several other languages in the same boat have done) is:

1. Saved the Calendar program, after conversion to upper case and a small marked alteration to give upper case output, to a text file called calendar_UC.txt.

2. Written another program called real_calendar.kt which takes calendar_UC.txt as input, outputs a runnable program called calendar_NC.kt to disk, compiles it to a .jar file, runs it, captures the output and prints it to the terminal (Ubuntu 14.04 being used). This program only makes the minimum changes to calendar_UC.txt to enable it to run. Everything else is left as upper case even though almost certainly no Kotlin programmer ("REAL" or not) would write such a program in practice.

This is calendar_UC.txt:

<lang scala>IMPORT JAVA.TEXT.* IMPORT JAVA.UTIL.* IMPORT JAVA.IO.PRINTSTREAM

INTERNAL FUN PRINTSTREAM.PRINTCALENDAR(YEAR: INT, NCOLS: BYTE, LOCALE: LOCALE?) {

   IF (NCOLS < 1 || NCOLS > 12)
       THROW ILLEGALARGUMENTEXCEPTION("ILLEGAL COLUMN WIDTH.")
   VAL W = NCOLS * 24
   VAL NROWS = MATH.CEIL(12.0 / NCOLS).TOINT()

   VAL DATE = GREGORIANCALENDAR(YEAR, 0, 1)
   VAR OFFS = DATE.GET(CALENDAR.DAY_OF_WEEK) - 1

   VAL DAYS = DATEFORMATSYMBOLS(LOCALE).SHORTWEEKDAYS.SLICE(1..7).MAP { IT.SLICE(0..1) }.JOINTOSTRING(" ", " ")
   VAL MONS = ARRAY(12) { ARRAY(8) { "" } }
   DATEFORMATSYMBOLS(LOCALE).MONTHS.SLICE(0..11).FOREACHINDEXED { M, NAME ->
       VAL LEN = 11 + NAME.LENGTH / 2
       VAL FORMAT = MESSAGEFORMAT.FORMAT("%{0}S%{1}S", LEN, 21 - LEN)
       MONS[M][0] = STRING.FORMAT(FORMAT, NAME, "")
       MONS[M][1] = DAYS
       VAL DIM = DATE.GETACTUALMAXIMUM(CALENDAR.DAY_OF_MONTH)
       FOR (D IN 1..42) {
           VAL ISDAY = D > OFFS && D <= OFFS + DIM
           VAL ENTRY = IF (ISDAY) STRING.FORMAT(" %2S", D - OFFS) ELSE "   "
           IF (D % 7 == 1)
               MONS[M][2 + (D - 1) / 7] = ENTRY
           ELSE
               MONS[M][2 + (D - 1) / 7] += ENTRY
       }
       OFFS = (OFFS + DIM) % 7
       DATE.ADD(CALENDAR.MONTH, 1)
   }

   PRINTF("%" + (W / 2 + 10) + "S%N", "[SNOOPY PICTURE]")
   PRINTF("%" + (W / 2 + 4) + "S%N%N", YEAR)

   FOR (R IN 0..NROWS - 1) {
       FOR (I IN 0..7) {
           VAR C = R * NCOLS
           WHILE (C < (R + 1) * NCOLS && C < 12) {
               PRINTF("   %S", MONS[C][I].TOUPPERCASE())  // ORIGINAL CHANGED TO PRINT IN UPPER CASE 
               C++
           }
           PRINTLN()
       }
       PRINTLN()
   }

}

FUN MAIN(ARGS: ARRAY<STRING>) {

   SYSTEM.OUT.PRINTCALENDAR(1969, 3, LOCALE.US)

}</lang>

and this is real_calendar.kt:

<lang scala>// version 1.1.3

import java.io.File import java.io.BufferedReader import java.io.InputStreamReader

fun main(args: Array<String>) {

   val keywords = listOf(
       "import", "internal", "fun", "if", "throw", "val", "var", "for", "in", "while"
   )
   val singleCase = listOf(
       "java.text",
       "java.util",
       "java.io",
       "else",     // really a keyword but doesn't have a following space here
       "ceil",
       "it",       // really a keyword but doesn't have a following space here
       "get(",     // also included in GETACTUALMAXIMUM       
       "slice",
       "map",
       "months",        
       "length",
       ".format",  // also variable called FORMAT        
       "add",
       "printf", 
       "println",
       "out",
       "main",
       "args",
       "s%{1}s",
       "%2s",
       "s%n%n",
       "s%n",
       "%s"
   ) 
        
   val mixedCase = listOf( 
       "PRINTSTREAM" to "PrintStream",
       "INT," to "Int,",  // also included in PRINTCALENDAR
       "BYTE" to "Byte",
       "LOCALE?" to "Locale?",  // also variable called LOCALE
       "LOCALE." to "Locale.",
       "ILLEGALARGUMENTEXCEPTION" to "IllegalArgumentException",
       "MATH" to "Math",
       "GREGORIANCALENDAR" to "GregorianCalendar",
       "DATEFORMATSYMBOLS" to "DateFormatSymbols",
       "ARRAY" to "Array",
       "MESSAGEFORMAT" to "MessageFormat",
       "JOINTOSTRING" to "joinToString",
       "STRING" to "String",
       "CALENDAR." to "Calendar.", // also included in PRINTCALENDAR
       "SYSTEM" to "System",
       "TOINT" to "toInt",
       "SHORTWEEKDAYS" to "shortWeekdays",
       "FOREACHINDEXED" to "forEachIndexed",
       "GETACTUALMAXIMUM" to "getActualMaximum",
       "TOUPPERCASE" to "toUpperCase"
   )
       
   var text = File("calendar_UC.txt").readText()
   for (k in keywords)   text = text.replace("${k.toUpperCase()} ", "$k ") // add a following space to be on safe side
   for (s in singleCase) text = text.replace(s.toUpperCase(), s)
   for (m in mixedCase)  text = text.replace(m.first, m.second)
   File("calendar_NC.kt").writeText(text)
   val commands = listOf("kotlinc", "calendar_NC.kt", "-include-runtime", "-d", "calendar_X.jar")
   val pb = ProcessBuilder(commands)
   pb.redirectErrorStream(true)
   val process = pb.start()
   process.waitFor()
   val commands2 = listOf("java", "-jar", "calendar_NC.jar")
   val pb2 = ProcessBuilder(commands2)
   pb2.redirectErrorStream(true)
   val process2 = pb2.start()
   val out = StringBuilder()
   val br = BufferedReader(InputStreamReader(process2.inputStream))
   while (true) {
       val line = br.readLine()
       if (line == null) break
       out.append(line).append('\n')
   }
   br.close()
   println(out.toString()) 

}</lang>

which generates (on disk) calendar_NC.kt:

<lang scala>import java.text.* import java.util.* import java.io.PrintStream

internal fun PrintStream.PRINTCALENDAR(YEAR: Int, NCOLS: Byte, LOCALE: Locale?) {

   if (NCOLS < 1 || NCOLS > 12)
       throw IllegalArgumentException("ILLEGAL COLUMN WIDTH.")
   val W = NCOLS * 24
   val NROWS = Math.ceil(12.0 / NCOLS).toInt()

   val DATE = GregorianCalendar(YEAR, 0, 1)
   var OFFS = DATE.get(Calendar.DAY_OF_WEEK) - 1

   val DAYS = DateFormatSymbols(LOCALE).shortWeekdays.slice(1..7).map { it.slice(0..1) }.joinToString(" ", " ")
   val MONS = Array(12) { Array(8) { "" } }
   DateFormatSymbols(LOCALE).months.slice(0..11).forEachIndexed { M, NAME ->
       val LEN = 11 + NAME.length / 2
       val FORMAT = MessageFormat.format("%{0}s%{1}s", LEN, 21 - LEN)
       MONS[M][0] = String.format(FORMAT, NAME, "")
       MONS[M][1] = DAYS
       val DIM = DATE.getActualMaximum(Calendar.DAY_OF_MONTH)
       for (D in 1..42) {
           val ISDAY = D > OFFS && D <= OFFS + DIM
           val ENTRY = if (ISDAY) String.format(" %2s", D - OFFS) else "   "
           if (D % 7 == 1)
               MONS[M][2 + (D - 1) / 7] = ENTRY
           else
               MONS[M][2 + (D - 1) / 7] += ENTRY
       }
       OFFS = (OFFS + DIM) % 7
       DATE.add(Calendar.MONTH, 1)
   }

   printf("%" + (W / 2 + 10) + "s%n", "[SNOOPY PICTURE]")
   printf("%" + (W / 2 + 4) + "s%n%n", YEAR)

   for (R in 0..NROWS - 1) {
       for (I in 0..7) {
           var C = R * NCOLS
           while (C < (R + 1) * NCOLS && C < 12) {
               printf("   %s", MONS[C][I].toUpperCase())  // ORIGINAL CHANGED TO PRINT in UPPER CASE 
               C++
           }
           println()
       }
       println()
   }

}

fun main(args: Array<String>) {

   System.out.PRINTCALENDAR(1969, 3, Locale.US)

}</lang>

which when compiled and run produces output of:

                              [SNOOPY PICTURE]
                                    1969

          JANUARY                 FEBRUARY                 MARCH        
    SU MO TU WE TH FR SA    SU MO TU WE TH FR SA    SU MO TU WE TH FR SA
              1  2  3  4                       1                       1
     5  6  7  8  9 10 11     2  3  4  5  6  7  8     2  3  4  5  6  7  8
    12 13 14 15 16 17 18     9 10 11 12 13 14 15     9 10 11 12 13 14 15
    19 20 21 22 23 24 25    16 17 18 19 20 21 22    16 17 18 19 20 21 22
    26 27 28 29 30 31       23 24 25 26 27 28       23 24 25 26 27 28 29
                                                    30 31               

           APRIL                    MAY                     JUNE        
    SU MO TU WE TH FR SA    SU MO TU WE TH FR SA    SU MO TU WE TH FR SA
           1  2  3  4  5                 1  2  3     1  2  3  4  5  6  7
     6  7  8  9 10 11 12     4  5  6  7  8  9 10     8  9 10 11 12 13 14
    13 14 15 16 17 18 19    11 12 13 14 15 16 17    15 16 17 18 19 20 21
    20 21 22 23 24 25 26    18 19 20 21 22 23 24    22 23 24 25 26 27 28
    27 28 29 30             25 26 27 28 29 30 31    29 30               
                                                                        

            JULY                   AUGUST                SEPTEMBER      
    SU MO TU WE TH FR SA    SU MO TU WE TH FR SA    SU MO TU WE TH FR SA
           1  2  3  4  5                    1  2        1  2  3  4  5  6
     6  7  8  9 10 11 12     3  4  5  6  7  8  9     7  8  9 10 11 12 13
    13 14 15 16 17 18 19    10 11 12 13 14 15 16    14 15 16 17 18 19 20
    20 21 22 23 24 25 26    17 18 19 20 21 22 23    21 22 23 24 25 26 27
    27 28 29 30 31          24 25 26 27 28 29 30    28 29 30            
                            31                                          

          OCTOBER                 NOVEMBER                DECEMBER      
    SU MO TU WE TH FR SA    SU MO TU WE TH FR SA    SU MO TU WE TH FR SA
              1  2  3  4                       1        1  2  3  4  5  6
     5  6  7  8  9 10 11     2  3  4  5  6  7  8     7  8  9 10 11 12 13
    12 13 14 15 16 17 18     9 10 11 12 13 14 15    14 15 16 17 18 19 20
    19 20 21 22 23 24 25    16 17 18 19 20 21 22    21 22 23 24 25 26 27
    26 27 28 29 30 31       23 24 25 26 27 28 29    28 29 30 31         
                            30                                          

Lua

Tested with Lua 5.3.2
Lua is case sensitive and all the keywords and library routines are in lower case. As with the D sample, we use a simple pre-processor to execute the (slightly modified) upper-cased source of the Lua solution for the standard Calendar task.
The upper case Lua source - stored in a file called UCCALENDAR.LUU:
<lang lua>FUNCTION PRINT_CAL(YEAR)

 LOCAL MONTHS={"JANUARY","FEBRUARY","MARCH","APRIL","MAY","JUNE",
               "JULY","AUGUST","SEPTEMBER","OCTOBER","NOVEMBER","DECEMBER"}
 LOCAL DAYSTITLE="MO TU WE TH FR SA SU"
 LOCAL DAYSPERMONTH={31,28,31,30,31,30,31,31,30,31,30,31}
 LOCAL STARTDAY=((YEAR-1)*365+MATH.FLOOR((YEAR-1)/4)-MATH.FLOOR((YEAR-1)/100)+MATH.FLOOR((YEAR-1)/400))%7
 IF YEAR%4==0 AND YEAR%100~=0 OR YEAR%400==0 THEN
   DAYSPERMONTH[2]=29
 END
 LOCAL SEP=5
 LOCAL MONTHWIDTH=DAYSTITLE:LEN()
 LOCAL CALWIDTH=3*MONTHWIDTH+2*SEP

 FUNCTION CENTER(STR, WIDTH)
   LOCAL FILL1=MATH.FLOOR((WIDTH-STR:LEN())/2)
   LOCAL FILL2=WIDTH-STR:LEN()-FILL1
   RETURN STRING.REP(" ",FILL1)..STR..STRING.REP(" ",FILL2)
 END

 FUNCTION MAKEMONTH(NAME, SKIP,DAYS)
   LOCAL CAL={
     CENTER(NAME,MONTHWIDTH),
     DAYSTITLE
   }
   LOCAL CURDAY=1-SKIP
   WHILE #CAL<9 DO
     LINE={}
     FOR I=1,7 DO
       IF CURDAY<1 OR CURDAY>DAYS THEN
         LINE[I]="  "
       ELSE
         LINE[I]=STRING.FORMAT("%2D",CURDAY)
       END
       CURDAY=CURDAY+1
     END
     CAL[#CAL+1]=TABLE.CONCAT(LINE," ")
   END
   RETURN CAL
 END

 LOCAL CALENDAR={}
 FOR I,MONTH IN IPAIRS(MONTHS) DO
   LOCAL DPM=DAYSPERMONTH[I]
   CALENDAR[I]=MAKEMONTH(MONTH, STARTDAY, DPM)
   STARTDAY=(STARTDAY+DPM)%7
 END


 PRINT(CENTER("[SNOOPY]",CALWIDTH):UPPER(),"\N")
 PRINT(CENTER("--- "..YEAR.." ---",CALWIDTH):UPPER(),"\N")

 FOR Q=0,3 DO
   FOR L=1,9 DO
     LINE={}
     FOR M=1,3 DO
       LINE[M]=CALENDAR[Q*3+M][L]
     END
     PRINT(TABLE.CONCAT(LINE,STRING.REP(" ",SEP)):UPPER())
   END
 END

END

PRINT_CAL(1969) </lang> The following "one-liner" standard Lua source will down-case and run the program in the source file specified as it's parameter (file luu.lua): <lang lua>do io.input( arg[ 1 ] ); local s = io.read( "*a" ):lower(); io.close(); assert( load( s ) )() end </lang> The following command will execute the UCCALENDAR.LUU source (replace lua532 with the appropriate command for your system):

lua532 luu.lua UCCALENDAR.LUU

Output:
                               [SNOOPY]                               	

                             --- 1969 ---                             	

      JANUARY                  FEBRUARY                  MARCH        
MO TU WE TH FR SA SU     MO TU WE TH FR SA SU     MO TU WE TH FR SA SU
       1  2  3  4  5                     1  2                     1  2
 6  7  8  9 10 11 12      3  4  5  6  7  8  9      3  4  5  6  7  8  9
13 14 15 16 17 18 19     10 11 12 13 14 15 16     10 11 12 13 14 15 16
20 21 22 23 24 25 26     17 18 19 20 21 22 23     17 18 19 20 21 22 23
27 28 29 30 31           24 25 26 27 28           24 25 26 27 28 29 30
                                                  31                  
                                                                      
       APRIL                     MAY                      JUNE        
MO TU WE TH FR SA SU     MO TU WE TH FR SA SU     MO TU WE TH FR SA SU
    1  2  3  4  5  6               1  2  3  4                        1
 7  8  9 10 11 12 13      5  6  7  8  9 10 11      2  3  4  5  6  7  8
14 15 16 17 18 19 20     12 13 14 15 16 17 18      9 10 11 12 13 14 15
21 22 23 24 25 26 27     19 20 21 22 23 24 25     16 17 18 19 20 21 22
28 29 30                 26 27 28 29 30 31        23 24 25 26 27 28 29
                                                  30                  
                                                                      
        JULY                    AUGUST                 SEPTEMBER      
MO TU WE TH FR SA SU     MO TU WE TH FR SA SU     MO TU WE TH FR SA SU
    1  2  3  4  5  6                  1  2  3      1  2  3  4  5  6  7
 7  8  9 10 11 12 13      4  5  6  7  8  9 10      8  9 10 11 12 13 14
14 15 16 17 18 19 20     11 12 13 14 15 16 17     15 16 17 18 19 20 21
21 22 23 24 25 26 27     18 19 20 21 22 23 24     22 23 24 25 26 27 28
28 29 30 31              25 26 27 28 29 30 31     29 30               
                                                                      
                                                                      
      OCTOBER                  NOVEMBER                 DECEMBER      
MO TU WE TH FR SA SU     MO TU WE TH FR SA SU     MO TU WE TH FR SA SU
       1  2  3  4  5                     1  2      1  2  3  4  5  6  7
 6  7  8  9 10 11 12      3  4  5  6  7  8  9      8  9 10 11 12 13 14
13 14 15 16 17 18 19     10 11 12 13 14 15 16     15 16 17 18 19 20 21
20 21 22 23 24 25 26     17 18 19 20 21 22 23     22 23 24 25 26 27 28
27 28 29 30 31           24 25 26 27 28 29 30     29 30 31            
                                                                      
                                                                      

Perl

Since we can't use eval or print (or any other keywords) at the top level, we need to abuse backticks in order to print anything, as in the infamous JAPH with no letters or numbers. Consequently, the calendar is printed to standard error instead of standard output.

<lang perl>$PROGRAM = '\'

MY @START_DOW = (3, 6, 6, 2, 4, 0,

                2, 5, 1, 3, 6, 1);

MY @DAYS = (31, 28, 31, 30, 31, 30,

           31, 31, 30, 31, 30, 31);

MY @MONTHS; FOREACH MY $M (0 .. 11) {

   FOREACH MY $R (0 .. 5) {
       $MONTHS[$M][$R] = JOIN " ",
           MAP { $_ < 1 || $_ > $DAYS[$M] ? "  " : SPRINTF "%2D", $_ }
           MAP { $_ - $START_DOW[$M] + 1 }
           $R * 7 .. $R * 7 + 6;
   }

}

SUB P { WARN $_[0], "\\N" } P UC " [INSERT SNOOPY HERE]"; P " 1969"; P ""; FOREACH (UC(" JANUARY FEBRUARY MARCH APRIL MAY JUNE"),

        UC("        JULY                 AUGUST              SEPTEMBER              OCTOBER               NOVEMBER              DECEMBER")) {
   P $_;
   MY @MS = SPLICE @MONTHS, 0, 6;
   P JOIN "  ", ((UC "SU MO TU WE TH FR SA") X 6);
   P JOIN "  ", MAP { SHIFT @$_ } @MS FOREACH 0 .. 5;

}

\;

  1. LOWERCASE LETTERS

$E = '%' | '@'; $C = '#' | '@'; $H = '(' | '@'; $O = '/' | '@'; $T = '4' | '@'; $R = '2' | '@'; $A = '!' | '@'; $Z = ':' | '@'; $P = '0' | '@'; $L = ',' | '@';

`${E}${C}${H}${O} $PROGRAM | ${T}${R} A-Z ${A}-${Z} | ${P}${E}${R}${L}`;</lang> Although, if we are abusing the backticks and other innocent programs, why not just: <lang Perl>$_=$ARGV[0]//1969;`\143\141\154 $_ >&2`</lang>

Perl 6

Uppercase is no challenge, who needs letters at all? [Requires the year to be supplied as a command-line argument, and Unixish cal command.] <lang perl6>$_="\0".."~";< 115 97 121 32 34 91 73 78 83 69 82 84 32 83 78 79 79 80 89 32 72 69 82 69 93 34 59 114 117 110 32 60 99 97 108 62 44 64 42 65 82 71 83 91 48 93 47 47 49 57 54 57 >."$_[99]$_[104]$_[114]$_[115]"()."$_[69]$_[86]$_[65]$_[76]"()</lang>

Phix

OK, I'm not going to take this too seriously but this is as good an opportunity as I'll ever get to showcase how trivial it is to make some rather fundamental changes to the compiler.

So, the first task is to take a copy of Calendar and make it output uppercase. Change the line <lang Phix>return repeat(' ',left)&s&repeat(' ',right)</lang> in routine centre to: <lang Phix>return repeat(' ',left)&upper(s)&repeat(' ',right)</lang> (That's that done.) Now, Phix is case-sensitive, and many of the keywords and builtins are in lower case, which presents a bit of a challenge - but we can cope.
It is too tedious and not particularly helpful to present a completed solution, instead I shall outline the (relatively simple) steps this would require. I have limited my tests to INCLUDE and INTEGER.

In psym.e you can find the line <lang Phix>initialSymEntry("integer", S_Type,"TI",opInt, E_none) -- #01 / 0b0001 integer</lang> Immediately after that (it should now be there commented out) add: <lang Phix>Alias("INTEGER",symlimit)</lang>

Add similar lines for length, floor, repeat, upper, day_of_week, sequence, string, sprintf, append, printf, join, at the appropriate places.

Keywords are handled slightly differently: In pttree.e we need a new alias routine (you should find this one commented out, from when I was testing all this): <lang Phix>procedure tt_stringA(sequence text, integer alias)

   tt_string(text,-2)
   tt[pcurr] = alias

end procedure</lang> and you can find the line <lang Phix>global constant T_include = 596 tt_stringF("include",T_include)</lang> Sometime after that, in fact after the very last use of tt_stringF, add (likewise you should find this one commented out): <lang Phix>tt_stringA("INCLUDE",T_include)</lang>

Add similar lines for function, end, iff, for, to, do, if, or, then, else, return, procedure, but this time all some ways away from the originals. Quickly run "p p" and make sure you get a normal prompt, without any "T_include should be 624(not 596)" or suchlike.

Currently ptok.e recognises \n but not \N. Search for all references to escchar (there should be one definition and two references) and make sure the character being checked is mapped to lower case, ie change (twice) <lang Phix>Ch = find(Ch,escchar)</lang> to <lang Phix>Ch = find(lower(Ch),escchar)</lang>

Lastly, the calendar example includes builtins\timedate.e, which contains some lower-case definitions. So copy it to (say) TIMEDATEUPPER.E and change adjust_timedate, timedelta, days (the 2nd param to timedelta), and format_timedate to their uppercase equivalents, and of course change that include to INCLUDE BUILTINS\TIMEDATEUPPER.E.

There is probably some change in ptok.e/pttree.e even simpler than the steps outlined above that makes everything case insensitive, but locating that is left as an exercise for the reader.

You don't actually have to repackage to test this, just run p p test.exw - percentagewise it might be ten times slower (as p.exw is much bigger than test.exw), but it'll still only be a fraction of a second.

Finally, you can take that copy of Calendar and make it all uppercase. In Edita (shipped with Phix) that is just <Ctrl A><Alt U>.

PHP

While PHP functions are case-sensitive (aside of _()), this isn't the case for language constructs.

<lang php><?PHP ECHO <<<REALPROGRAMMERSTHINKINUPPERCASEANDCHEATBYUSINGPRINT

      JANUARY               FEBRUARY               MARCH                 APRIL                  MAY                   JUNE
MO TU WE TH FR SA SO  MO TU WE TH FR SA SO  MO TU WE TH FR SA SO  MO TU WE TH FR SA SO  MO TU WE TH FR SA SO  MO TU WE TH FR SA SO
       1  2  3  4  5                  1  2                  1  2      1  2  3  4  5  6            1  2  3  4                     1
 6  7  8  9 10 11 12   3  4  5  6  7  8  9   3  4  5  6  7  8  9   7  8  9 10 11 12 13   5  6  7  8  9 10 11   2  3  4  5  6  7  8
13 14 15 16 17 18 19  10 11 12 13 14 15 16  10 11 12 13 14 15 16  14 15 16 17 18 19 20  12 13 14 15 16 17 18   9 10 11 12 13 14 15
20 21 22 23 24 25 26  17 18 19 20 21 22 23  17 18 19 20 21 22 23  21 22 23 24 25 26 27  19 20 21 22 23 24 25  16 17 18 19 20 21 22
27 28 29 30 31        24 25 26 27 28        24 25 26 27 28 29 30  28 29 30              26 27 28 29 30 31     23 24 25 26 27 28 29
                                            31                                                                30 
        JULY                 AUGUST               SEPTEMBER              OCTOBER              NOVEMBER              DECEMBER
MO TU WE TH FR SA SO  MO TU WE TH FR SA SO  MO TU WE TH FR SA SO  MO TU WE TH FR SA SO  MO TU WE TH FR SA SO  MO TU WE TH FR SA SO
    1  2  3  4  5  6               1  2  3   1  2  3  4  5  6  7         1  2  3  4  5                  1  2   1  2  3  4  5  6  7
 7  8  9 10 11 12 13   4  5  6  7  8  9 10   8  9 10 11 12 13 14   6  7  8  9 10 11 12   3  4  5  6  7  8  9   8  9 10 11 12 13 14
14 15 16 17 18 19 20  11 12 13 14 15 16 17  15 16 17 18 19 20 21  13 14 15 16 17 18 19  10 11 12 13 14 15 16  15 16 17 18 19 20 21
21 22 23 24 25 26 27  18 19 20 21 22 23 24  22 23 24 25 26 27 28  20 21 22 23 24 25 26  17 18 19 20 21 22 23  22 23 24 25 26 27 28
28 29 30 31           25 26 27 28 29 30 31  29 30                 27 28 29 30 31        24 25 26 27 28 29 30  29 30 31

REALPROGRAMMERSTHINKINUPPERCASEANDCHEATBYUSINGPRINT

                                                                                                            ; // MAGICAL SEMICOLON</lang>

PicoLisp

The "CALENDAR.L" source file: <lang PicoLisp>(DE CAL (YEAR)

  (PRINL "====== " YEAR " ======")
  (FOR DAT (RANGE (DATE YEAR 1 1) (DATE YEAR 12 31))
     (LET D (DATE DAT)
        (TAB (3 3 4 8)
           (WHEN (= 1 (CADDR D))
              (GET `(INTERN (PACK (MAPCAR CHAR (42 77 111 110)))) (CADR D)) )
           (CADDR D)
           (DAY DAT `(INTERN (PACK (MAPCAR CHAR (42 68 97 121)))))
           (WHEN (=0 (% (INC DAT) 7))
              (PACK (CHAR 87) "EEk " (WEEK DAT)) ) ) ) ) )

(CAL 1969) (BYE)</lang> Then it can be executed with this command line:

$ pil -'load (list "awk" "{print tolower($0)}" "CALENDAR.L")'
Output:
====== 1969 ======
Jan  1 Wed
     2 Thu
     3 Fri
     4 Sat
     5 Sun
     6 Mon  Week 2
     7 Tue
....
    28 Sat
    29 Sun
    30 Mon Week 27
Jul  1 Tue
     2 Wed
     3 Thu
     4 Fri
....
    25 Thu
    26 Fri
    27 Sat
    28 Sun
    29 Mon Week 53
    30 Tue
    31 Wed

PL/I

<lang PL/I>(SUBRG, SIZE, FOFL): CALENDAR: PROCEDURE (YEAR) OPTIONS (MAIN);

  DECLARE YEAR CHARACTER (4) VARYING;
  DECLARE (A, B, C) (0:5,0:6) CHARACTER (3);
  DECLARE NAME_MONTH(12) STATIC CHARACTER (9) VARYING INITIAL (
     'JANUARY', 'FEBRUARY', 'MARCH',     'APRIL',   'MAY',      'JUNE',
     'JULY',    'AUGUST',   'SEPTEMBER', 'OCTOBER', 'NOVEMBER', 'DECEMBER'); 
  DECLARE I FIXED;
  DECLARE (MM, MMP1, MMP2) PIC '99';
  PUT EDIT (CENTER('CALENDAR FOR ' || YEAR, 67)) (A);
  PUT SKIP (2);
  DO MM = 1 TO 12 BY 3;
     MMP1 = MM + 1; MMP2 = MM + 2;
     CALL PREPARE_MONTH('01' || MM   || YEAR, A);
     CALL PREPARE_MONTH('01' || MMP1 || YEAR, B);
     CALL PREPARE_MONTH('01' || MMP2 || YEAR, C);
     PUT SKIP EDIT (CENTER(NAME_MONTH(MM),   23),
                    CENTER(NAME_MONTH(MMP1), 23),
                    CENTER(NAME_MONTH(MMP2), 23) ) (A);
     PUT SKIP EDIT ((3)'  M  T  W  T  F  S  S  ') (A);
     DO I = 0 TO 5;
        PUT SKIP EDIT (A(I,*), B(I,*), C(I,*)) (7 A, X(2));
     END;
  END;

PREPARE_MONTH: PROCEDURE (START, MONTH);

  DECLARE MONTH(0:5,0:6) CHARACTER (3);
  DECLARE START CHARACTER (8);
  DECLARE I PIC 'ZZ9';
  DECLARE OFFSET FIXED;
  DECLARE (J, DAY) FIXED BINARY (31);
  DECLARE (THIS_MONTH, NEXT_MONTH, K) FIXED BINARY;
  DAY = DAYS(START, 'DDMMYYYY');
  OFFSET = WEEKDAY(DAY) - 1;
  IF OFFSET  = 0 THEN OFFSET = 7;
  MONTH = ;
  DO J = DAY BY 1;
     THIS_MONTH = SUBSTR(DAYSTODATE(J,   'DDMMYYYY'), 3, 2);
     NEXT_MONTH = SUBSTR(DAYSTODATE(J+1, 'DDMMYYYY'), 3, 2);
     IF THIS_MONTH^= NEXT_MONTH THEN LEAVE;
  END;
  I = 1;
  DO K = OFFSET-1 TO OFFSET+J-DAY-1;
     MONTH(K/7, MOD(K,7)) = I; I = I + 1;
  END;

END PREPARE_MONTH;

END CALENDAR;</lang> See CALENDAR for result.

Python

<lang python> import subprocess px = subprocess.Popen(['python', '-c', 'import calendar; calendar.prcal(1969)'],

                     stdout=subprocess.PIPE)

cal = px.communicate()[0] print (cal.upper()) </lang>

Racket

<lang racket>

  1. CI(MODULE NAME-OF-THIS-FILE RACKET

(REQUIRE RACKET/DATE) (DEFINE (CALENDAR YR)

 (DEFINE (NSPLIT N L) (IF (NULL? L) L (CONS (TAKE L N) (NSPLIT N (DROP L N)))))
 (DEFINE MONTHS
   (FOR/LIST ([MN (IN-NATURALS 1)]
              [MNAME '(JANUARY FEBRUARY MARCH APRIL MAY JUNE JULY
                       AUGUST SEPTEMBER OCTOBER NOVEMBER DECEMBER)])
     (DEFINE S (FIND-SECONDS 0 0 12 1 MN YR))
     (DEFINE PFX (DATE-WEEK-DAY (SECONDS->DATE S)))
     (DEFINE DAYS
       (LET ([? (IF (= MN 12) (Λ(X Y) Y) (Λ(X Y) X))])
         (ROUND (/ (- (FIND-SECONDS 0 0 12 1 (? (+ 1 MN) 1) (? YR (+ 1 YR))) S)
                   60 60 24))))
     (LIST* (~A MNAME #:WIDTH 20 #:ALIGN 'CENTER) "SU MO TU WE TH FR SA"
            (MAP STRING-JOIN
                 (NSPLIT 7 `(,@(MAKE-LIST PFX "  ")
                             ,@(FOR/LIST ([D DAYS])
                                 (~A (+ D 1) #:WIDTH 2 #:ALIGN 'RIGHT))
                             ,@(MAKE-LIST (- 42 PFX DAYS) "  ")))))))
 (LET* ([S '(" 11,-~4-._3. 41-4! 10/ ()=(2) 3\\ 40~A! 9( 3( 80 39-4! 10\\._\\"
             ", ,-4'! 5#2X3@7! 12/ 2-3'~2;! 11/ 4/~2|-! 9=( 3~4 2|! 3/~42\\! "
             "2/_23\\! /_25\\!/_27\\! 3|_20|! 3|_20|! 3|_20|! 3| 20|!!")]
        [S (REGEXP-REPLACE* "!" (STRING-APPEND* S) "~%")]
        [S (REGEXP-REPLACE* "@" S (STRING-FOLDCASE "X"))]
        [S (REGEXP-REPLACE* ".(?:[1-7][0-9]*|[1-9])" S
             (Λ(M) (MAKE-STRING (STRING->NUMBER (SUBSTRING M 1))
                                (STRING-REF M 0))))])
   (PRINTF S YR))
 (FOR-EACH (COMPOSE1 DISPLAYLN STRING-TITLECASE)
   (DROPF-RIGHT (FOR*/LIST ([3MS (NSPLIT 3 MONTHS)] [S (APPLY MAP LIST 3MS)])
                  (REGEXP-REPLACE " +$" (STRING-JOIN S "   ") ""))
                (Λ(S) (EQUAL? "" S)))))

(CALENDAR 1969)) </lang>

REXX

This is essentially the same REXX program as for the CALENDAR task, but written entirely in uppercase. Indeed,
it could be written without any Latin (or any language) letters of any kind for the REXX program's variables.

From the task's description, I took it to mean the program was to be in all uppercase, but the output was
still supposed to look pretty (that is, partly in lowercase). Even so, on the (line) printers that were used
long ago, the printers (if not supporting lowercase), would print lowercase as uppercase (with the FOLD option).

The other REXX program made use of lowercase letters for determining the minimum length of any of the options
(from the command line), and a few simple tricks were used to accomplish this.
[Note: the command line may also be all uppercase.]

In any case, both versions of the programs' output are identical (but the second REXX version sure as heck looks
like it was beat with a big ole ugly stick ─── and pardon the strong language). <lang rexx>/*REXX PROGRAM TO SHOW ANY YEAR'S (MONTHLY) CALENDAR (WITH/WITHOUT GRID)*/ @ABC= DO J=0 TO 255;_=D2C(J);IF DATATYPE(_,'L') THEN @ABC=@ABC||_;END @ABCU=@ABC; UPPER @ABCU DAYS_='SUNDAY MONDAY TUESDAY WEDNESDAY THURSDAY FRIDAY SATURDAY' MONTHS_='JANUARY FEBRUARY MARCH APRIL MAY JUNE JULY AUGUST SEPTEMBER OCTOBER NOVEMBER DECEMBER' DAYS=; MONTHS=

   DO J=1 FOR 7
   _=LOWER(WORD(DAYS_,J))
   DAYS=DAYS TRANSLATE(LEFT(_,1))SUBSTR(_,2)
   END
         DO J=1 FOR 12
         _=LOWER(WORD(MONTHS_,J))
         MONTHS=MONTHS TRANSLATE(LEFT(_,1))SUBSTR(_,2)
         END

CALFILL=' '; MC=12; _='1 3 1234567890' "FB"X PARSE VAR _ GRID CALSPACES # CHK . CV_ DAYS.1 DAYS.2 DAYS.3 DAYSN SD SW _=0; PARSE VAR _ COLS 1 JD 1 LOWERCASE 1 MAXKALPUTS 1 NARROW 1,

                NARROWER 1 NARROWEST 1 SHORT 1 SHORTER 1 SHORTEST 1,
                SMALL 1 SMALLER 1 SMALLEST 1 UPPERCASE

PARSE ARG MM '/' DD "/" YYYY _ '(' OPS; UOPS=OPS IF _\== | \IS#(MM) | \IS#(DD) | \IS#(YYYY) THEN CALL ERX 86

@CALMONTHS ='CALMON' || LOWER('THS') @CALSPACES ='CALSP' || LOWER('ACES') @DEPTH ='DEP' || LOWER('TH') @GRIDS ='GRID' || LOWER('S') @LOWERCASE ='LOW' || LOWER('ERCASE') @NARROW ='NAR' || LOWER('ROW') @NARROWER ='NARROWER' @NARROWEST ='NARROWES' || LOWER('T') @SHORT ='SHOR' || LOWER('T') @SHORTER ='SHORTER' @SHORTEST ='SHORTES' || LOWER('T') @UPPERCASE ='UPP' || LOWER('ERCASE') @WIDTH ='WID' || LOWER('TH')

 DO WHILE OPS\==; OPS=STRIP(OPS,'L'); PARSE VAR OPS _1 2 1 _ . 1 _O OPS
 UPPER _
      SELECT
      WHEN  ABB(@CALMONTHS)  THEN        MC=NAI()
      WHEN  ABB(@CALSPACES)  THEN CALSPACES=NAI()
      WHEN  ABB(@DEPTH)      THEN        SD=NAI()
      WHEN ABBN(@GRIDS)      THEN      GRID=NO()
      WHEN ABBN(@LOWERCASE)  THEN LOWERCASE=NO()
      WHEN ABBN(@NARROW)     THEN    NARROW=NO()
      WHEN ABBN(@NARROWER)   THEN  NARROWER=NO()
      WHEN ABBN(@NARROWEST)  THEN NARROWEST=NO()
      WHEN ABBN(@SHORT)      THEN     SHORT=NO()
      WHEN ABBN(@SHORTER)    THEN   SHORTER=NO()
      WHEN ABBN(@SHORTEST)   THEN  SHORTEST=NO()
      WHEN ABBN(@SMALL)      THEN     SMALL=NO()
      WHEN ABBN(@SMALLER)    THEN   SMALLER=NO()
      WHEN ABBN(@SMALLEST)   THEN  SMALLEST=NO()
      WHEN ABBN(@UPPERCASE)  THEN UPPERCASE=NO()
      WHEN  ABB(@WIDTH)      THEN        SW=NAI()
      OTHERWISE NOP
      END    /*SELECT*/
 END         /*DO WHILE OPTS\== ...*/

MC=INT(MC,'MONTHSCALENDER'); IF MC>0 THEN CAL=1 DAYS=' 'DAYS; MONTHS=' 'MONTHS CYYYY=RIGHT(DATE(),4); HYY=LEFT(CYYYY,2); LYY=RIGHT(CYYYY,2) DY.=31; _=30; PARSE VAR _ DY.4 1 DY.6 1 DY.9 1 DY.11; DY.2=28+LY(YYYY) YY=RIGHT(YYYY,2); SD=P(SD 43); SW=P(SW 80); CW=10; CINDENT=1; CALWIDTH=76 IF SMALL THEN DO; NARROW=1  ; SHORT=1  ; END IF SMALLER THEN DO; NARROWER=1 ; SHORTER=1 ; END IF SMALLEST THEN DO; NARROWEST=1; SHORTEST=1; END IF SHORTEST THEN SHORTER=1 IF SHORTER THEN SHORT =1 IF NARROW THEN DO; CW=9; CINDENT=3; CALWIDTH=69; END IF NARROWER THEN DO; CW=4; CINDENT=1; CALWIDTH=34; END IF NARROWEST THEN DO; CW=2; CINDENT=1; CALWIDTH=20; END CV_=CALWIDTH+CALSPACES+2 CALFILL=LEFT(COPIES(CALFILL,CW),CW)

     DO J=1 FOR 7;         _=WORD(DAYS,J)
           DO JW=1 FOR 3;  _D=STRIP(SUBSTR(_,CW*JW-CW+1,CW))
           IF JW=1 THEN _D=CENTRE(_D,CW+1)
                   ELSE _D=LEFT(_D,CW+1)
           DAYS.JW=DAYS.JW||_D
           END   /*JW*/
     __=DAYSN
     IF NARROWER  THEN DAYSN=__||CENTRE(LEFT(_,3),5)
     IF NARROWEST THEN DAYSN=__||CENTER(LEFT(_,2),3)
     END   /*J*/

_YYYY=YYYY; CALPUTS=0; CV=1; _MM=MM+0; MONTH=WORD(MONTHS,MM) DY.2=28+LY(_YYYY); DIM=DY._MM; _DD=01; DOW=DOW(_MM,_DD,_YYYY); $DD=DD+0

/*─────────────────────────────NOW: THE BUSINESS OF THE BUILDING THE CAL*/ CALL CALGEN

              DO _J=2 TO MC
              IF CV_\== THEN DO
                               CV=CV+CV_
                               IF CV+CV_>=SW THEN DO; CV=1; CALL CALPUT
                                                  CALL FCALPUTS;CALL CALPB
                                                  END
                                             ELSE CALPUTS=0
                               END
                          ELSE DO;CALL CALPB;CALL CALPUT;CALL FCALPUTS;END
              _MM=_MM+1;  IF _MM==13 THEN DO;  _MM=1; _YYYY=_YYYY+1;  END
              MONTH=WORD(MONTHS,_MM); DY.2=28+LY(_YYYY); DIM=DY._MM
              DOW=DOW(_MM,_DD,_YYYY); $DD=0; CALL CALGEN
              END   /*_J*/

CALL FCALPUTS RETURN _

/*─────────────────────────────CALGEN SUBROUTINE────────────────────────*/ CALGEN: CELLX=;CELLJ=;CELLM=;CALCELLS=0;CALLINE=0 CALL CALPUT CALL CALPUTL COPIES('─',CALWIDTH),"┌┐"; CALL CALHD CALL CALPUTL MONTH ' ' _YYYY  ; CALL CALHD IF NARROWEST | NARROWER THEN CALL CALPUTL DAYSN

                       ELSE DO JW=1 FOR 3
                            IF SPACE(DAYS.JW)\== THEN CALL CALPUTL DAYS.JW
                            END

CALFT=1; CALFB=0

 DO JF=1 FOR DOW-1; CALL CELLDRAW CALFILL,CALFILL; END
 DO JY=1 FOR DIM; CALL CELLDRAW JY; END

CALFB=1

 DO 7; CALL CELLDRAW CALFILL,CALFILL; END

IF SD>32 & \SHORTER THEN CALL CALPUT RETURN

/*─────────────────────────────CELLDRAW SUBROUTINE──────────────────────*/ CELLDRAW: PARSE ARG ZZ,CDDOY;ZZ=RIGHT(ZZ,2);CALCELLS=CALCELLS+1 IF CALCELLS>7 THEN DO

                  CALLINE=CALLINE+1
                  CELLX=SUBSTR(CELLX,2)
                  CELLJ=SUBSTR(CELLJ,2)
                  CELLM=SUBSTR(CELLM,2)
                  CELLB=TRANSLATE(CELLX,,")(─-"#)
                  IF CALLINE==1 THEN CALL CX
                  CALL CALCSM; CALL CALPUTL CELLX; CALL CALCSJ; CALL CX
                  CELLX=; CELLJ=; CELLM=; CALCELLS=1
                  END

CDDOY=RIGHT(CDDOY,CW); CELLM=CELLM'│'CENTER(,CW) CELLX=CELLX'│'CENTRE(ZZ,CW); CELLJ=CELLJ'│'CENTER(,CW) RETURN

/*═════════════════════════════GENERAL 1-LINE SUBS══════════════════════*/ ABB:ARG ABBU;PARSE ARG ABB;RETURN ABBREV(ABBU,_,ABBL(ABB)) ABBL:RETURN VERIFY(ARG(1)LEFT(@ABC,1),@ABC,'M')-1 ABBN:PARSE ARG ABBN;RETURN ABB(ABBN)|ABB('NO'ABBN) CALCSJ:IF SD>49&\SHORTER THEN CALL CALPUTL CELLB;IF SD>24&\SHORT THEN CALL CALPUTL CELLJ; RETURN CALCSM:IF SD>24&\SHORT THEN CALL CALPUTL CELLM;IF SD>49&\SHORTER THEN CALL CALPUTL CELLB;RETURN CALHD:IF SD>24&\SHORTER THEN CALL CALPUTL;IF SD>32&\SHORTEST THEN CALL CALPUTL;RETURN CALPB:IF \GRID&SHORTEST THEN CALL PUT CHK;RETURN CALPUT:CALPUTS=CALPUTS+1;MAXKALPUTS=MAX(MAXKALPUTS,CALPUTS);IF SYMBOL('CT.'CALPUTS)\=='VAR' THEN CT.CALPUTS=;CT.CALPUTS=OVERLAY(ARG(1),CT.CALPUTS,CV);RETURN CALPUTL:CALL CALPUT COPIES(' ',CINDENT)LEFT(ARG(2)"│",1)CENTER(ARG(1),CALWIDTH)||RIGHT('│'ARG(2),1);RETURN CX:CX_='├┤';CX=COPIES(COPIES('─',CW)'┼',7);IF CALFT THEN DO;CX=TRANSLATE(CX,'┬',"┼");CALFT=0;END;IF CALFB THEN DO;CX=TRANSLATE(CX,'┴',"┼");CX_='└┘';CALFB=0;END;CALL CALPUTL CX,CX_;RETURN DOW:PROCEDURE;ARG M,D,Y;IF M<3 THEN DO;M=M+12;Y=Y-1;END;YL=LEFT(Y,2);YR=RIGHT(Y,2);W=(D+(M+1)*26%10+YR+YR%4+YL%4+5*YL)//7;IF W==0 THEN W=7;RETURN W ER:PARSE ARG _1,_2;CALL '$ERR' "14"P(_1) P(WORD(_1,2) !FID(1)) _2;IF _1<0 THEN RETURN _1;EXIT RESULT ERR:CALL ER '-'ARG(1),ARG(2);RETURN ERX:CALL ER '-'ARG(1),ARG(2);EXIT FCALPUTS: DO J=1 FOR MAXKALPUTS;CALL PUT CT.J;END;CT.=;MAXKALPUTS=0;CALPUTS=0;RETURN INT:INT=NUMX(ARG(1),ARG(2));IF \ISINT(INT) THEN CALL ERX 92,ARG(1) ARG(2);RETURN INT/1 IS#:RETURN VERIFY(ARG(1),#)==0 ISINT:RETURN DATATYPE(ARG(1),'W') LOWER:RETURN TRANSLATE(ARG(1),@ABC,@ABCU) LY:ARG _;IF LENGTH(_)==2 THEN _=HYY||_;LY=_//4==0;IF LY==0 THEN RETURN 0;LY=((_//100\==0)|_//400==0);RETURN LY NA:IF ARG(1)\== THEN CALL ERX 01,ARG(2);PARSE VAR OPS NA OPS;IF NA== THEN CALL ERX 35,_O;RETURN NA NAI:RETURN INT(NA(),_O) NAN:RETURN NUMX(NA(),_O) NO:IF ARG(1)\== THEN CALL ERX 01,ARG(2);RETURN LEFT(_,2)\=='NO' NUM:PROCEDURE;PARSE ARG X .,F,Q;IF X== THEN RETURN X;IF DATATYPE(X,'N') THEN RETURN X/1;X=SPACE(TRANSLATE(X,,','),0);IF DATATYPE(X,'N') THEN RETURN X/1;RETURN NUMNOT() NUMNOT:IF Q==1 THEN RETURN X;IF Q== THEN CALL ER 53,X F;CALL ERX 53,X F NUMX:RETURN NUM(ARG(1),ARG(2),1) P:RETURN WORD(ARG(1),1) PUT:_=ARG(1);_=TRANSLATE(_,,'_'CHK);IF \GRID THEN _=UNGRID(_);IF LOWERCASE THEN _=LOWER(_);IF UPPERCASE THEN UPPER _;IF SHORTEST&_=' ' THEN RETURN;CALL TELL _;RETURN TELL:SAY ARG(1);RETURN UNGRID:RETURN TRANSLATE(ARG(1),,"│║─═┤┐└┴┬├┼┘┌╔╗╚╝╟╢╞╡╫╪╤╧╥╨╠╣")</lang>

Output:

when using the input of

1/1/1969 (noGrid shortest narrowest)
                          «Snoopy "picture" here»

     January   1969          February   1969            March   1969
  Su Mo Tu We Th Fr Sa     Su Mo Tu We Th Fr Sa     Su Mo Tu We Th Fr Sa
            1  2  3  4                        1                        1
   5  6  7  8  9 10 11      2  3  4  5  6  7  8      2  3  4  5  6  7  8
  12 13 14 15 16 17 18      9 10 11 12 13 14 15      9 10 11 12 13 14 15
  19 20 21 22 23 24 25     16 17 18 19 20 21 22     16 17 18 19 20 21 22
  26 27 28 29 30 31        23 24 25 26 27 28        23 24 25 26 27 28 29
                                                    30 31
      April   1969              May   1969              June   1969
  Su Mo Tu We Th Fr Sa     Su Mo Tu We Th Fr Sa     Su Mo Tu We Th Fr Sa
         1  2  3  4  5                  1  2  3      1  2  3  4  5  6  7
   6  7  8  9 10 11 12      4  5  6  7  8  9 10      8  9 10 11 12 13 14
  13 14 15 16 17 18 19     11 12 13 14 15 16 17     15 16 17 18 19 20 21
  20 21 22 23 24 25 26     18 19 20 21 22 23 24     22 23 24 25 26 27 28
  27 28 29 30              25 26 27 28 29 30 31     29 30
      July   1969             August   1969           September   1969
  Su Mo Tu We Th Fr Sa     Su Mo Tu We Th Fr Sa     Su Mo Tu We Th Fr Sa
         1  2  3  4  5                     1  2         1  2  3  4  5  6
   6  7  8  9 10 11 12      3  4  5  6  7  8  9      7  8  9 10 11 12 13
  13 14 15 16 17 18 19     10 11 12 13 14 15 16     14 15 16 17 18 19 20
  20 21 22 23 24 25 26     17 18 19 20 21 22 23     21 22 23 24 25 26 27
  27 28 29 30 31           24 25 26 27 28 29 30     28 29 30
                           31
     October   1969          November   1969          December   1969
  Su Mo Tu We Th Fr Sa     Su Mo Tu We Th Fr Sa     Su Mo Tu We Th Fr Sa
            1  2  3  4                        1         1  2  3  4  5  6
   5  6  7  8  9 10 11      2  3  4  5  6  7  8      7  8  9 10 11 12 13
  12 13 14 15 16 17 18      9 10 11 12 13 14 15     14 15 16 17 18 19 20
  19 20 21 22 23 24 25     16 17 18 19 20 21 22     21 22 23 24 25 26 27
  26 27 28 29 30 31        23 24 25 26 27 28 29     28 29 30 31
                           30

Ring

<lang ring>

  1. PROJECT : CALENDAR - FOR "REAL" PROGRAMMERS
  2. DATE  : 2018/06/28
  3. AUTHOR : GAL ZSOLT (~ CALMOSOFT ~)
  4. EMAIL  : <CALMOSOFT@GMAIL.COM>

LOAD "GUILIB.RING" LOAD "STDLIB.RING"

NEW QAPP

      {
       WIN1 = NEW QWIDGET() {
                  DAY = LIST(12)
                  POS = NEWLIST(12,37)
                  MONTH = LIST(12)
                  WEEK = LIST(7)
                  WEEKDAY = LIST(7)
                  BUTTON = NEWLIST(7,6)
                  MONTHSNAMES = LIST(12)
                  WEEK = ["SU", "MO", "TU", "WE", "TH", "FR", "SA"]
                  MONTHS = ["JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUNE", "JULY",
                                  "AUGUST", "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER"]
                  DAYSNEW = [[5,1], [6,2], [7,3], [1,4], [2,5], [3,6], [4,7]]
                  MO = [4,0,0,3,5,1,3,6,2,4,0,2]
                  MON = [31,28,31,30,31,30,31,31,30,31,30,31]
                  M2 = (((1969-1900)%7) + FLOOR((1969 - 1900)/4) % 7) % 7
                  FOR N = 1 TO 12
                       MONTH[N] = (MO[N] + M2) % 7
                       X = (MONTH[N] + 1) % 7 + 1
                      FOR M = 1 TO LEN(DAYSNEW)
                           IF DAYSNEW[M][1] = X
                             NR = M
                          OK
                      NEXT
                      DAY[N] = DAYSNEW[NR][2]
                 NEXT
                 FOR M = 1 TO 12
                      FOR N = 1 TO DAY[M] - 1
                           POS[M][N] = "  "
                      NEXT
                 NEXT
                 FOR M = 1 TO 12
                      FOR  N = DAY[M] TO 37
                            IF N < (MON[M] + DAY[M])
                               POS[M][N] = N - DAY[M] + 1
                            ELSE
                               POS[M][N] = "  "
                            OK
                      NEXT
                 NEXT
                 SETWINDOWTITLE("CALENDAR")
                 SETGEOMETRY(100,100,650,800)
                 LABEL1 = NEW QLABEL(WIN1) {
                             SETGEOMETRY(10,10,800,600)
                             SETTEXT("")
                 }
                YEAR = NEW QPUSHBUTTON(WIN1)
                                                 {
                                                 SETGEOMETRY(280,20,63,20)
                                                 YEAR.SETTEXT("1969")
                                                 }
                FOR N = 1 TO 4
                     NR = (N-1)*3+1
                    SHOWMONTHS(NR)
                NEXT
                FOR N = 1 TO 12
                    SHOWWEEKS(N)
                NEXT
                FOR N = 1 TO 12
                    SHOWDAYS(N)
                NEXT
                SHOW()
       }
       EXEC()
       }

FUNC SHOWMONTHS(M)

      FOR N = M TO M + 2
           MONTHSNAMES[N] = NEW QPUSHBUTTON(WIN1)
                                       {
                                       IF N%3 = 1
                                          COL = 120
                                          ROWNR = FLOOR(N/3)          
                                          IF ROWNR = 0
                                             ROWNR = N/3
                                          OK
                                          IF N = 1
                                             ROW = 40
                                          ELSE
                                             ROW = 40+ROWNR*180
                                          OK
                                       ELSE
                                          COLNR = N%3
                                          IF COLNR = 0
                                             COLNR = 3
                                          OK
                                          ROWNR = FLOOR(N/3)
                                          IF N%3 = 0
                                             ROWNR = FLOOR(N/3)-1
                                          OK
                                          COL = 120 + (COLNR-1)*160
                                          ROW = 40 + ROWNR*180
                                       OK
                                       SETGEOMETRY(COL,ROW,63,20)
                                       MONTHSNAMES[N].SETTEXT(MONTHS[N])
                                       }
      NEXT

FUNC SHOWWEEKS(N)

       FOR M = 1 TO 7
            COL = M%7
            IF COL = 0 COL = 7 OK
            WEEKDAY[M] = NEW QPUSHBUTTON(WIN1)
                                 {
                                 COLNR = N % 3
                                 IF COLNR = 0
                                    COLNR = 3
                                 OK
                                 ROWNR = FLOOR(N/3) 
                                 IF N%3 = 0
                                    ROWNR = FLOOR(N/3)-1
                                 OK
                                 COLBEGIN = 60 + (COLNR-1)*160
                                 ROWBEGIN = 60 + (ROWNR)*180
                                 SETGEOMETRY(COLBEGIN+COL*20,ROWBEGIN,25,20)
                                 WEEKDAY[M].SETTEXT(WEEK[M])
                                 }
       NEXT

FUNC SHOWDAYS(IND)

       ROWNR = FLOOR(IND/3)
       IF IND%3 = 0
          ROWNR = FLOOR(IND/3)-1
       OK
       ROWBEGIN = 60+ROWNR*180
       FOR M = 1 TO 6
            FOR N = 1 TO 7
                 COL = N%7
                 IF COL = 0 COL = 7 OK
                 ROW = M
                  BUTTON[N][M] = NEW QPUSHBUTTON(WIN1)
                                        {
                                         IF IND%3 = 1
                                            COLBEGIN = 60
                                         ELSEIF IND%3 = 2
                                            COLBEGIN = 220
                                         ELSE
                                            COLBEGIN = 380
                                         OK
                                         SETGEOMETRY(COLBEGIN+COL*20,ROWBEGIN+ROW*20,25,20)
                                         NR = (M-1)*7+N
                                         IF NR <= 37
                                            IF POS[IND][NR] != "  "
                                               BUTTON[N][M].SETTEXT(STRING(POS[IND][NR]))
                                            OK
                                         OK
                                         }
            NEXT
       NEXT

</lang> Output:

CALENDAR - FOR "REAL" PROGRAMMERS

Ruby

UPPERCASE RUBY is normally impossible, because Ruby is sensitive to case, and most methods and keywords have lowercase letters. To solve this task, we wrote a new program loader for UPPERCASE RUBY programs.

Our program loader responds to unknown method calls by calling their lowercase equivalents, so Kernel#PUTS acts like Kernel#puts. Our program loader also defines Object#RESCUE to replace the 'rescue' keyword. We can now write UPPERCASE RUBY programs that call uppercase methods and use no lowercase keywords.

  • loadup.rb is the program loader.

<lang ruby># loadup.rb - run UPPERCASE RUBY program

class Object

 alias lowercase_method_missing method_missing
 # Allow UPPERCASE method calls.
 def method_missing(sym, *args, &block)
   str = sym.to_s
   if str == (down = str.downcase)
     lowercase_method_missing sym, *args, &block
   else
     send down, *args, &block
   end
 end
 # RESCUE an exception without the 'rescue' keyword.
 def RESCUE(_BEGIN, _CLASS, _RESCUE)
   begin _BEGIN.CALL
   rescue _CLASS
     _RESCUE.CALL; end
 end

end

_PROGRAM = ARGV.SHIFT _PROGRAM || ABORT("USAGE: #{$0} PROGRAM.RB ARGS...") LOAD($0 = _PROGRAM)</lang>

Works with: Ruby version 1.8.7

<lang ruby># CAL.RB - CALENDAR REQUIRE 'DATE'.DOWNCASE

  1. FIND CLASSES.

OBJECT = [].CLASS.SUPERCLASS DATE = OBJECT.CONST_GET('DATE'.DOWNCASE.CAPITALIZE)

  1. CREATES A CALENDAR OF _YEAR_. RETURNS THIS CALENDAR AS A MULTI-LINE
  2. STRING FIT TO _COLUMNS_.

OBJECT.SEND(:DEFINE_METHOD, :CAL) {|_YEAR, _COLUMNS|

 # START AT JANUARY 1.
 #
 # DATE::ENGLAND MARKS THE SWITCH FROM JULIAN CALENDAR TO GREGORIAN
 # CALENDAR AT 1752 SEPTEMBER 14. THIS REMOVES SEPTEMBER 3 TO 13 FROM
 # YEAR 1752. (BY FORTUNE, IT KEEPS JANUARY 1.)
 #
 _DATE = DATE.NEW(_YEAR, 1, 1, DATE::ENGLAND)
 # COLLECT CALENDARS OF ALL 12 MONTHS.
 _MONTHS = (1..12).COLLECT {|_MONTH|
   _ROWS = [DATE::MONTHNAMES[_MONTH].UPCASE.CENTER(20),
            "SU MO TU WE TH FR SA"]
   # MAKE ARRAY OF 42 DAYS, STARTING WITH SUNDAY.
   _DAYS = []
   _DATE.WDAY.TIMES { _DAYS.PUSH "  " }
   CATCH(:BREAK) {
     LOOP {
       (_DATE.MONTH == _MONTH) || THROW(:BREAK)
       _DAYS.PUSH("%2D".DOWNCASE % _DATE.MDAY)
       _DATE += 1 }}
   (42 - _DAYS.LENGTH).TIMES { _DAYS.PUSH "  " }
   _DAYS.EACH_SLICE(7) {|_WEEK| _ROWS.PUSH(_WEEK.JOIN " ") }
   _ROWS }
 # CALCULATE MONTHS PER ROW (MPR).
 #  1. DIVIDE COLUMNS BY 22 COLUMNS PER MONTH, ROUNDED DOWN. (PRETEND
 #     TO HAVE 2 EXTRA COLUMNS; LAST MONTH USES ONLY 20 COLUMNS.)
 #  2. DECREASE MPR IF 12 MONTHS WOULD FIT IN THE SAME MONTHS PER
 #     COLUMN (MPC). FOR EXAMPLE, IF WE CAN FIT 5 MPR AND 3 MPC, THEN
 #     WE USE 4 MPR AND 3 MPC.
 _MPR = (_COLUMNS + 2).DIV 22
 _MPR = 12.DIV((12 + _MPR - 1).DIV _MPR)
 # USE 20 COLUMNS PER MONTH + 2 SPACES BETWEEN MONTHS.
 _WIDTH = _MPR * 22 - 2
 # JOIN MONTHS INTO CALENDAR.
 _ROWS = ["[SNOOPY]".CENTER(_WIDTH), "#{_YEAR}".CENTER(_WIDTH)]
 _MONTHS.EACH_SLICE(_MPR) {|_SLICE|
   _SLICE[0].EACH_INDEX {|_I|
     _ROWS.PUSH(_SLICE.MAP {|_A| _A[_I]}.JOIN "  ") }}
 _ROWS.JOIN("\012") }


(ARGV.LENGTH == 1) || ABORT("USAGE: #{$0} YEAR")

  1. GUESS WIDTH OF TERMINAL.
  2. 1. OBEY ENVIRONMENT VARIABLE COLUMNS.
  3. 2. TRY TO REQUIRE 'IO/CONSOLE' FROM RUBY 1.9.3.
  4. 3. TRY TO RUN `TPUT CO`.
  5. 4. ASSUME 80 COLUMNS.

LOADERROR = OBJECT.CONST_GET('LOAD'.DOWNCASE.CAPITALIZE +

                            'ERROR'.DOWNCASE.CAPITALIZE)

STANDARDERROR = OBJECT.CONST_GET('STANDARD'.DOWNCASE.CAPITALIZE +

                                'ERROR'.DOWNCASE.CAPITALIZE)

_INTEGER = 'INTEGER'.DOWNCASE.CAPITALIZE _TPUT_CO = 'TPUT CO'.DOWNCASE _COLUMNS = RESCUE(PROC {SEND(_INTEGER, ENV["COLUMNS"] || "")},

                 STANDARDERROR,
                 PROC {
                   RESCUE(PROC {
                            REQUIRE 'IO/CONSOLE'.DOWNCASE
                            IO.CONSOLE.WINSIZE[1]
                          }, LOADERROR,
                          PROC {
                            RESCUE(PROC {
                                     SEND(_INTEGER, `#{_TPUT_CO}`)
                                   }, STANDARDERROR,
                                   PROC {80}) }) })

PUTS CAL(ARGV[0].TO_I, _COLUMNS)</lang>

  • A local variable must start with a lowercase letter or an underscore, so we have many leading underscores (_YEAR, _COLUMN, _DATE and so on).
  • We form blocks with curly braces { ... }, never with lowercase keywords do ... end.
  • OBJECT = [].CLASS.SUPERCLASS finds the superclass of the class of the empty array; this is the Object class! Class#CONST_GET finds some other classes.
  • Class#DEFINE_METHOD defines a new method, Object#CAL, without a def keyword.
  • Kernel#LOOP, Kernel#THROW, Kernel#CATCH and operator || act like a while loop without a while keyword.
$ ruby loadup.rb CAL.RB 1969   
                                                             [SNOOPY]                                                             
                                                               1969                                                               
      JANUARY               FEBRUARY               MARCH                 APRIL                  MAY                   JUNE        
SU MO TU WE TH FR SA  SU MO TU WE TH FR SA  SU MO TU WE TH FR SA  SU MO TU WE TH FR SA  SU MO TU WE TH FR SA  SU MO TU WE TH FR SA
          1  2  3  4                     1                     1         1  2  3  4  5               1  2  3   1  2  3  4  5  6  7
 5  6  7  8  9 10 11   2  3  4  5  6  7  8   2  3  4  5  6  7  8   6  7  8  9 10 11 12   4  5  6  7  8  9 10   8  9 10 11 12 13 14
12 13 14 15 16 17 18   9 10 11 12 13 14 15   9 10 11 12 13 14 15  13 14 15 16 17 18 19  11 12 13 14 15 16 17  15 16 17 18 19 20 21
19 20 21 22 23 24 25  16 17 18 19 20 21 22  16 17 18 19 20 21 22  20 21 22 23 24 25 26  18 19 20 21 22 23 24  22 23 24 25 26 27 28
26 27 28 29 30 31     23 24 25 26 27 28     23 24 25 26 27 28 29  27 28 29 30           25 26 27 28 29 30 31  29 30               
                                            30 31                                                                                 
        JULY                 AUGUST              SEPTEMBER              OCTOBER               NOVEMBER              DECEMBER      
SU MO TU WE TH FR SA  SU MO TU WE TH FR SA  SU MO TU WE TH FR SA  SU MO TU WE TH FR SA  SU MO TU WE TH FR SA  SU MO TU WE TH FR SA
       1  2  3  4  5                  1  2      1  2  3  4  5  6            1  2  3  4                     1      1  2  3  4  5  6
 6  7  8  9 10 11 12   3  4  5  6  7  8  9   7  8  9 10 11 12 13   5  6  7  8  9 10 11   2  3  4  5  6  7  8   7  8  9 10 11 12 13
13 14 15 16 17 18 19  10 11 12 13 14 15 16  14 15 16 17 18 19 20  12 13 14 15 16 17 18   9 10 11 12 13 14 15  14 15 16 17 18 19 20
20 21 22 23 24 25 26  17 18 19 20 21 22 23  21 22 23 24 25 26 27  19 20 21 22 23 24 25  16 17 18 19 20 21 22  21 22 23 24 25 26 27
27 28 29 30 31        24 25 26 27 28 29 30  28 29 30              26 27 28 29 30 31     23 24 25 26 27 28 29  28 29 30 31         
                      31                                                                30                                        

Seed7

Seed7 keywords are lower case, so this silly solution uses the whole Calendar Task code, with small changes and all in upper case, in a text file named "CALENDAR.TXT":

$ INCLUDE "SEED7_05.S7I";
  INCLUDE "TIME.S7I";
 
CONST FUNC STRING: CENTER (IN STRING: STRI, IN INTEGER: LENGTH) IS
  RETURN ("" LPAD (LENGTH - LENGTH(STRI)) DIV 2 <& STRI) RPAD LENGTH;
 
CONST PROC: PRINTCALENDAR (IN INTEGER: YEAR, IN INTEGER: COLS) IS FUNC
  LOCAL
    VAR TIME: DATE IS TIME.VALUE;
    VAR INTEGER: DAYOFWEEK IS 0;
    CONST ARRAY STRING: MONTHNAMES IS [] ("JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUNE",
        "JULY", "AUGUST", "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER"); 
    VAR ARRAY ARRAY STRING: MONTHTABLE IS 12 TIMES 9 TIMES "";
    VAR STRING: STR IS "";
    VAR INTEGER: MONTH IS 0;
    VAR INTEGER: POSITION IS 0;
    VAR INTEGER: ROW IS 0;
    VAR INTEGER: COLUMN IS 0;
    VAR INTEGER: LINE IS 0;
  BEGIN
    FOR MONTH RANGE 1 TO 12 DO
      MONTHTABLE[MONTH][1] := " " & CENTER(UPPER(MONTHNAMES[MONTH]), 20);
      MONTHTABLE[MONTH][2] := UPPER(" MO TU WE TH FR SA SU");
      DATE := DATE(YEAR, MONTH, 1);
      DAYOFWEEK := DAYOFWEEK(DATE);
      FOR POSITION RANGE 1 TO 43 DO
        IF POSITION >= DAYOFWEEK AND POSITION - DAYOFWEEK < DAYSINMONTH(DATE.YEAR, DATE.MONTH) THEN
          STR := SUCC(POSITION - DAYOFWEEK) LPAD 3;
        ELSE
          STR := "" LPAD 3;
        END IF;
        MONTHTABLE[MONTH][3 + PRED(POSITION) DIV 7] &:= STR;
      END FOR;
    END FOR;
    WRITELN(CENTER(UPPER("[SNOOPY PICTURE]"), COLS * 24 + 4));
    WRITELN(CENTER(STR(YEAR),COLS * 24 + 4));
    WRITELN;
    FOR ROW RANGE 1 TO SUCC(11 DIV COLS) DO
      FOR LINE RANGE 1 TO 9 DO
        FOR COLUMN RANGE 1 TO COLS DO
          IF PRED(ROW) * COLS + COLUMN <= 12 THEN
            WRITE("   " & MONTHTABLE[PRED(ROW) * COLS + COLUMN][LINE]);
          END IF;
        END FOR;
        WRITELN;
      END FOR;
    END FOR;
  END FUNC;
 
CONST PROC: MAIN IS FUNC
  BEGIN
    PRINTCALENDAR(1969, 3);
  END FUNC;

Then in another program the file CALENDAR.TXT is read, converted, parsed and executed: <lang seed7>$ include "seed7_05.s7i";

 include "getf.s7i";
 include "progs.s7i";

const proc: main is func

 local
   var string: source is "";
 begin
   source := lower(getf("CALENDAR.TXT"));
   source := replace(source, "dayofweek", "dayOfWeek");
   source := replace(source, "daysinmonth", "daysInMonth");
   execute(parseStri(source));
 end func;</lang>
Output:
                              [SNOOPY PICTURE]                              
                                    1969                                    

          JANUARY                 FEBRUARY                 MARCH        
    MO TU WE TH FR SA SU    MO TU WE TH FR SA SU    MO TU WE TH FR SA SU
           1  2  3  4  5                    1  2                    1  2
     6  7  8  9 10 11 12     3  4  5  6  7  8  9     3  4  5  6  7  8  9
    13 14 15 16 17 18 19    10 11 12 13 14 15 16    10 11 12 13 14 15 16
    20 21 22 23 24 25 26    17 18 19 20 21 22 23    17 18 19 20 21 22 23
    27 28 29 30 31          24 25 26 27 28          24 25 26 27 28 29 30
                                                    31                  
                  
           APRIL                    MAY                     JUNE        
    MO TU WE TH FR SA SU    MO TU WE TH FR SA SU    MO TU WE TH FR SA SU
        1  2  3  4  5  6              1  2  3  4                       1
     7  8  9 10 11 12 13     5  6  7  8  9 10 11     2  3  4  5  6  7  8
    14 15 16 17 18 19 20    12 13 14 15 16 17 18     9 10 11 12 13 14 15
    21 22 23 24 25 26 27    19 20 21 22 23 24 25    16 17 18 19 20 21 22
    28 29 30                26 27 28 29 30 31       23 24 25 26 27 28 29
                                                    30                  
                  
            JULY                   AUGUST                SEPTEMBER      
    MO TU WE TH FR SA SU    MO TU WE TH FR SA SU    MO TU WE TH FR SA SU
        1  2  3  4  5  6                 1  2  3     1  2  3  4  5  6  7
     7  8  9 10 11 12 13     4  5  6  7  8  9 10     8  9 10 11 12 13 14
    14 15 16 17 18 19 20    11 12 13 14 15 16 17    15 16 17 18 19 20 21
    21 22 23 24 25 26 27    18 19 20 21 22 23 24    22 23 24 25 26 27 28
    28 29 30 31             25 26 27 28 29 30 31    29 30               
                                                                        
                  
          OCTOBER                 NOVEMBER                DECEMBER      
    MO TU WE TH FR SA SU    MO TU WE TH FR SA SU    MO TU WE TH FR SA SU
           1  2  3  4  5                    1  2     1  2  3  4  5  6  7
     6  7  8  9 10 11 12     3  4  5  6  7  8  9     8  9 10 11 12 13 14
    13 14 15 16 17 18 19    10 11 12 13 14 15 16    15 16 17 18 19 20 21
    20 21 22 23 24 25 26    17 18 19 20 21 22 23    22 23 24 25 26 27 28
    27 28 29 30 31          24 25 26 27 28 29 30    29 30 31            

Sidef

<lang ruby>-> DT { ('DATE'.("\LWC") + 'TIME'.("\LWC")).("\LREQUIRE") }

-> MONTHS_PER_COL { 6 } -> WEEK_DAY_NAMES { <MO TU WE TH FR SA SU> } -> MONTH_NAMES { <JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC> }

-> FMT_MONTH (YEAR, MONTH, STR="", WEEK_DAY=0) {

   STR  = "%11\LS\E%9\LS\E\12".("\LSPRINTF")(MONTH_NAMES()[MONTH-1],)
   STR += (WEEK_DAY_NAMES().("\LJOIN")(' ') + "\12")
   -> DATE { DT().("\LNEW")("\LYEAR" => YEAR, "\LMONTH" => MONTH) }
   WEEK_DAY = DATE().("\LDAY_OF_WEEK")
   STR += (["  "] * WEEK_DAY-1 -> ("\LJOIN")(" "))
   -> LAST_DAY {
       DT().("\LLAST_DAY_OF_MONTH")(
           "\LYEAR" => YEAR, "\LMONTH" => MONTH
       ).("\LDAY")
   }
   (DATE().("\LDAY") .. LAST_DAY()).("\LEACH")({ |DAY|
       (WEEK_DAY ~~ (2..7)) && (STR += " ")
       (WEEK_DAY == 8) && (
           STR += "\12"
           WEEK_DAY = 1
       )
       STR += ("%2\LD" % DAY)
       ++WEEK_DAY
   })
   (WEEK_DAY < 8) && (STR += " ")
   STR += (["  "] * 8-WEEK_DAY -> ("\LJOIN")(" "))
   STR += "\12"

}

-> FMT_YEAR (YEAR, STR="", MONTH_STRS=[]) {

   MONTH_STRS = 12.("\LOF")({|I| FMT_MONTH(YEAR, I+1).("\LLINES") })
   STR += (' '*(MONTHS_PER_COL()*10 + 2) + YEAR + "\12")
   (0..11 -> ("\LBY")(MONTHS_PER_COL())).("\LEACH")({ |MONTH|
       MONTH_STRS[MONTH] && ->() {
           { |I|
               MONTH_STRS[MONTH + I] && (
                   STR += MONTH_STRS[MONTH + I].("\LSHIFT")
                   STR += ' '*2
               )
           } * MONTHS_PER_COL()
           STR += "\12"
           MONTH_STRS[MONTH] && __FUNC__()
       }()
       STR += "\12"
   })
   STR

}

FMT_YEAR(ARGV ? ARGV[0].("\LTO_I") : 1969).("\LPRINT")</lang>

Output:
                                                              1969
        JAN                   FEB                   MAR                   APR                   MAY                   JUN           
MO TU WE TH FR SA SU  MO TU WE TH FR SA SU  MO TU WE TH FR SA SU  MO TU WE TH FR SA SU  MO TU WE TH FR SA SU  MO TU WE TH FR SA SU  
       1  2  3  4  5                  1  2                  1  2      1  2  3  4  5  6            1  2  3  4                     1  
 6  7  8  9 10 11 12   3  4  5  6  7  8  9   3  4  5  6  7  8  9   7  8  9 10 11 12 13   5  6  7  8  9 10 11   2  3  4  5  6  7  8  
13 14 15 16 17 18 19  10 11 12 13 14 15 16  10 11 12 13 14 15 16  14 15 16 17 18 19 20  12 13 14 15 16 17 18   9 10 11 12 13 14 15  
20 21 22 23 24 25 26  17 18 19 20 21 22 23  17 18 19 20 21 22 23  21 22 23 24 25 26 27  19 20 21 22 23 24 25  16 17 18 19 20 21 22  
27 28 29 30 31        24 25 26 27 28        24 25 26 27 28 29 30  28 29 30              26 27 28 29 30 31     23 24 25 26 27 28 29  

        JUL                   AUG                   SEP                   OCT                   NOV                   DEC           
MO TU WE TH FR SA SU  MO TU WE TH FR SA SU  MO TU WE TH FR SA SU  MO TU WE TH FR SA SU  MO TU WE TH FR SA SU  MO TU WE TH FR SA SU  
    1  2  3  4  5  6               1  2  3   1  2  3  4  5  6  7         1  2  3  4  5                  1  2   1  2  3  4  5  6  7  
 7  8  9 10 11 12 13   4  5  6  7  8  9 10   8  9 10 11 12 13 14   6  7  8  9 10 11 12   3  4  5  6  7  8  9   8  9 10 11 12 13 14  
14 15 16 17 18 19 20  11 12 13 14 15 16 17  15 16 17 18 19 20 21  13 14 15 16 17 18 19  10 11 12 13 14 15 16  15 16 17 18 19 20 21  
21 22 23 24 25 26 27  18 19 20 21 22 23 24  22 23 24 25 26 27 28  20 21 22 23 24 25 26  17 18 19 20 21 22 23  22 23 24 25 26 27 28  
28 29 30 31           25 26 27 28 29 30 31  29 30                 27 28 29 30 31        24 25 26 27 28 29 30  29 30 31              

Tcl

The program starts implementing aliases for all built-in commands. This is done without using any letters at all ;). CALENDER takes arguments of year and optional terminal width to use. <lang tcl> \146\157\162\145\141\143\150 42 [\151\156\146\157 \143\157\155\155\141\156\144\163] { \145\166\141\154 " \160\162\157\143 [\163\164\162\151\156\147 \164\157\165\160\160\145\162 $42] {\141\162\147\163} \{ \163\145\164 \151 1 \146\157\162\145\141\143\150 \141 \$\141\162\147\163 \{ \151\146 \[\163\164\162\151\156\147 \155\141\164\143\150 _ \$\141\] \{\151\156\143\162 \151; \143\157\156\164\151\156\165\145\} \151\146 \$\151%2 \{\154\141\160\160\145\156\144 \156\141\162\147\163 \[\163\164\162\151\156\147 \164\157\154\157\167\145\162 \$\141\]\} \{\154\141\160\160\145\156\144 \156\141\162\147\163 \$\141\} \} \165\160\154\145\166\145\154 \"$42 \$\156\141\162\147\163\" \} " }

PROC _ CPUTS {L S} { UPVAR _ CAL CAL APPEND _ CAL($L) $S } PROC _ CENTER {S LN} { SET _ C [STRING LENGTH $S] SET _ L [EXPR _ ($LN-$C)/2]; SET _ R [EXPR _ $LN-$L-$C] FORMAT "%${L}S%${C}S%${R}S" _ "" $S "" } PROC _ CALENDAR {{YEAR 1969} {WIDTH 80}} { ARRAY SET CAL "" SET _ YRS [EXPR $YEAR-1584] SET _ SDAY [EXPR (6+$YRS+(($YRS+3)/4)-(($YRS-17)/100+1)+(($YRS+383)/400))%7] CPUTS 0 [CENTER "(SNOOPY)" [EXPR $WIDTH/25*25]]; CPUTS 1 "" CPUTS 2 [CENTER "--- $YEAR ---" [EXPR $WIDTH/25*25]]; CPUTS 3 "" FOR _ {SET _ NR 0} {$NR<=11} {INCR _ NR} { SET _ LINE [EXPR ($NR/($WIDTH/25))*8+4] SET _ NAME [LINDEX _ "JANUARY FEBRUARY MARCH APRIL MAY JUNE JULY AUGUST SEPTEMBER OCTOBER NOVEMBER DECEMBER" $NR] SET _ DAYS [EXPR 31-((($NR)%7)%2)-($NR==1)*(2-((($YEAR%4==0)&&($YEAR%100>0))||($YEAR%400==0)))] CPUTS $LINE "[CENTER $NAME 20] " CPUTS [INCR _ LINE] "MO TU WE TH FR SA SU "; INCR _ LINE SET _ DAY [EXPR 1-$SDAY] FOR _ {SET _ X 0} {$X<42} {INCR _ X} { IF _ ($DAY>0)&&($DAY<=$DAYS) {CPUTS $LINE [FORMAT "%2d " $DAY]} {CPUTS $LINE " "} IF _ (($X+1)%7)==0 {CPUTS $LINE " "; INCR _ LINE} INCR _ DAY } SET _ SDAY [EXPR ($SDAY+($DAYS%7))%7] } FOR _ {SET _ X 0} {$X<[ARRAY SIZE _ CAL]} {INCR _ X} { PUTS _ $CAL($X) } }

CALENDAR </lang>

Output:
                                 (SNOOPY)                                  

                               --- 1969 ---                                

      JANUARY                  FEBRUARY                  MARCH             
MO TU WE TH FR SA SU     MO TU WE TH FR SA SU     MO TU WE TH FR SA SU     
       1  2  3  4  5                     1  2                     1  2     
 6  7  8  9 10 11 12      3  4  5  6  7  8  9      3  4  5  6  7  8  9     
13 14 15 16 17 18 19     10 11 12 13 14 15 16     10 11 12 13 14 15 16     
20 21 22 23 24 25 26     17 18 19 20 21 22 23     17 18 19 20 21 22 23     
27 28 29 30 31           24 25 26 27 28           24 25 26 27 28 29 30     
                                                  31                       
       APRIL                     MAY                      JUNE             
MO TU WE TH FR SA SU     MO TU WE TH FR SA SU     MO TU WE TH FR SA SU     
    1  2  3  4  5  6               1  2  3  4                        1     
 7  8  9 10 11 12 13      5  6  7  8  9 10 11      2  3  4  5  6  7  8     
14 15 16 17 18 19 20     12 13 14 15 16 17 18      9 10 11 12 13 14 15     
21 22 23 24 25 26 27     19 20 21 22 23 24 25     16 17 18 19 20 21 22     
28 29 30                 26 27 28 29 30 31        23 24 25 26 27 28 29     
                                                  30                       
        JULY                    AUGUST                 SEPTEMBER           
MO TU WE TH FR SA SU     MO TU WE TH FR SA SU     MO TU WE TH FR SA SU     
    1  2  3  4  5  6                  1  2  3      1  2  3  4  5  6  7     
 7  8  9 10 11 12 13      4  5  6  7  8  9 10      8  9 10 11 12 13 14     
14 15 16 17 18 19 20     11 12 13 14 15 16 17     15 16 17 18 19 20 21     
21 22 23 24 25 26 27     18 19 20 21 22 23 24     22 23 24 25 26 27 28     
28 29 30 31              25 26 27 28 29 30 31     29 30                    
                                                                           
      OCTOBER                  NOVEMBER                 DECEMBER           
MO TU WE TH FR SA SU     MO TU WE TH FR SA SU     MO TU WE TH FR SA SU     
       1  2  3  4  5                     1  2      1  2  3  4  5  6  7     
 6  7  8  9 10 11 12      3  4  5  6  7  8  9      8  9 10 11 12 13 14     
13 14 15 16 17 18 19     10 11 12 13 14 15 16     15 16 17 18 19 20 21     
20 21 22 23 24 25 26     17 18 19 20 21 22 23     22 23 24 25 26 27 28     
27 28 29 30 31           24 25 26 27 28 29 30     29 30 31                 

UNIX Shell

<lang shell>CAL=CAL TR=TR A=A Z=Z LANG=C ${CAL,,} 1969 | ${TR,,} ${A,}-${Z,} A-Z</lang>

Output:
                               1969                               

       JANUARY               FEBRUARY                 MARCH       
MO TU WE TH FR SA SU   MO TU WE TH FR SA SU   MO TU WE TH FR SA SU
       1  2  3  4  5                   1  2                   1  2
 6  7  8  9 10 11 12    3  4  5  6  7  8  9    3  4  5  6  7  8  9
13 14 15 16 17 18 19   10 11 12 13 14 15 16   10 11 12 13 14 15 16
20 21 22 23 24 25 26   17 18 19 20 21 22 23   17 18 19 20 21 22 23
27 28 29 30 31         24 25 26 27 28         24 25 26 27 28 29 30
                                              31                  
        APRIL                   MAY                   JUNE        
MO TU WE TH FR SA SU   MO TU WE TH FR SA SU   MO TU WE TH FR SA SU
    1  2  3  4  5  6             1  2  3  4                      1
 7  8  9 10 11 12 13    5  6  7  8  9 10 11    2  3  4  5  6  7  8
14 15 16 17 18 19 20   12 13 14 15 16 17 18    9 10 11 12 13 14 15
21 22 23 24 25 26 27   19 20 21 22 23 24 25   16 17 18 19 20 21 22
28 29 30               26 27 28 29 30 31      23 24 25 26 27 28 29
                                              30                  
        JULY                  AUGUST                SEPTEMBER     
MO TU WE TH FR SA SU   MO TU WE TH FR SA SU   MO TU WE TH FR SA SU
    1  2  3  4  5  6                1  2  3    1  2  3  4  5  6  7
 7  8  9 10 11 12 13    4  5  6  7  8  9 10    8  9 10 11 12 13 14
14 15 16 17 18 19 20   11 12 13 14 15 16 17   15 16 17 18 19 20 21
21 22 23 24 25 26 27   18 19 20 21 22 23 24   22 23 24 25 26 27 28
28 29 30 31            25 26 27 28 29 30 31   29 30               
                                                                  
       OCTOBER               NOVEMBER               DECEMBER      
MO TU WE TH FR SA SU   MO TU WE TH FR SA SU   MO TU WE TH FR SA SU
       1  2  3  4  5                   1  2    1  2  3  4  5  6  7
 6  7  8  9 10 11 12    3  4  5  6  7  8  9    8  9 10 11 12 13 14
13 14 15 16 17 18 19   10 11 12 13 14 15 16   15 16 17 18 19 20 21
20 21 22 23 24 25 26   17 18 19 20 21 22 23   22 23 24 25 26 27 28
27 28 29 30 31         24 25 26 27 28 29 30   29 30 31            

Vedit macro language

In Calendar task, standard calendar.vdm macro was called to draw one month calendar. The version here is stand-alone and contains subroutine DRAW_CALENDAR to draw one month calendar.

In addition, short commands are used here. (Normally, long versions of command words are used in RC tasks for readability.) Vedit macro language is case insensitive, but it is normal practice to write short commands in upper case.

<lang vedit>BS(BF) CFT(22)

  1. 3 = 6 // NUMBER OF MONTHS PER LINE
  2. 2 = 1969 // YEAR
  3. 1 = 1 // STARTING MONTH

IC(' ', COUNT, #3*9) IT("[SNOOPY]") IN(2) IC(' ', COUNT, #3*9+1) NI(#2) IN REPEAT(12/#3) {

   REPEAT (#3) {
       BS(BF)

CALL("DRAW_CALENDAR") RCB(10, 1, EOB_POS, COLSET, 1, 21) BQ(OK) #5 = CP RI(10) GP(#5) EOL IC(9) #1++

   }
   EOF IN(2)

} RETURN

DRAW_CALENDAR:

NUM_PUSH(4,20)

  1. 20 = RF

BOF DC(ALL)

NI(#1, LEFT+NOCR) IT("/1/") NI(#2, LEFT+NOCR) RCB(#20, BOL_POS, EOL_POS, DELETE)

  1. 10 = JDATE(@(#20))
  1. 4 = #2+(#1==12)

NI(#1%12+1, LEFT+NOCR) IT("/1/") NI(#4, LEFT+NOCR) RCB(#20, BOL_POS, CP, DELETE)

  1. 11 = JDATE(@(#20)) - #10
  2. 7 = (#10-1) % 7

IF (#1==1) { RS(#20," JANUARY ") } IF (#1==2) { RS(#20," FEBRUARY") } IF (#1==3) { RS(#20," MARCH ") } IF (#1==4) { RS(#20," APRIL ") } IF (#1==5) { RS(#20," MAY ") } IF (#1==6) { RS(#20," JUNE ") } IF (#1==7) { RS(#20," JULY ") } IF (#1==8) { RS(#20," AUGUST ") } IF (#1==9) { RS(#20,"SEPTEMBER") } IF (#1==10) { RS(#20," OCTOBER ") } IF (#1==11) { RS(#20," NOVEMBER") } IF (#1==12) { RS(#20," DECEMBER") }

IT(" ") RI(#20) IN IT(" MO TU WE TH FR SA SU") IN IT(" --------------------") IN IC(' ', COUNT, #7*3) FOR (#8 = 1; #8 <= #11; #8++) {

   NI(#8, COUNT, 3)
   #5 = (#8+#10+5) % 7
   IF (#5 == 6) { IN }

} IT(" ")

REG_EMPTY(#20) NUM_POP(4,20) RETURN </lang>

                                                      [SNOOPY]

                                                        1969

       JANUARY               FEBRUARY               MARCH                 APRIL                  MAY                  JUNE          
 MO TU WE TH FR SA SU  MO TU WE TH FR SA SU  MO TU WE TH FR SA SU  MO TU WE TH FR SA SU  MO TU WE TH FR SA SU  MO TU WE TH FR SA SU
 --------------------  --------------------  --------------------  --------------------  --------------------  --------------------
        1  2  3  4  5                  1  2                  1  2      1  2  3  4  5  6            1  2  3  4                     1
  6  7  8  9 10 11 12   3  4  5  6  7  8  9   3  4  5  6  7  8  9   7  8  9 10 11 12 13   5  6  7  8  9 10 11   2  3  4  5  6  7  8
 13 14 15 16 17 18 19  10 11 12 13 14 15 16  10 11 12 13 14 15 16  14 15 16 17 18 19 20  12 13 14 15 16 17 18   9 10 11 12 13 14 15
 20 21 22 23 24 25 26  17 18 19 20 21 22 23  17 18 19 20 21 22 23  21 22 23 24 25 26 27  19 20 21 22 23 24 25  16 17 18 19 20 21 22
 27 28 29 30 31        24 25 26 27 28        24 25 26 27 28 29 30  28 29 30              26 27 28 29 30 31     23 24 25 26 27 28 29
                                             31                                                                30

        JULY                  AUGUST              SEPTEMBER              OCTOBER               NOVEMBER              DECEMBER       
 MO TU WE TH FR SA SU  MO TU WE TH FR SA SU  MO TU WE TH FR SA SU  MO TU WE TH FR SA SU  MO TU WE TH FR SA SU  MO TU WE TH FR SA SU
 --------------------  --------------------  --------------------  --------------------  --------------------  --------------------
     1  2  3  4  5  6               1  2  3   1  2  3  4  5  6  7         1  2  3  4  5                  1  2   1  2  3  4  5  6  7
  7  8  9 10 11 12 13   4  5  6  7  8  9 10   8  9 10 11 12 13 14   6  7  8  9 10 11 12   3  4  5  6  7  8  9   8  9 10 11 12 13 14
 14 15 16 17 18 19 20  11 12 13 14 15 16 17  15 16 17 18 19 20 21  13 14 15 16 17 18 19  10 11 12 13 14 15 16  15 16 17 18 19 20 21
 21 22 23 24 25 26 27  18 19 20 21 22 23 24  22 23 24 25 26 27 28  20 21 22 23 24 25 26  17 18 19 20 21 22 23  22 23 24 25 26 27 28
 28 29 30 31           25 26 27 28 29 30 31  29 30                 27 28 29 30 31        24 25 26 27 28 29 30  29 30 31

XLISP

XLISP isn't case-sensitive, so in principle it would be possible just to reproduce the solution given in the "ordinary" Calendar task. But that program makes use of recursion, "fancy" data structures, long variable names, pretty-printy indentation, and a whole host of other features that I don't think REAL programmers like any better than they like lower case: so, instead, here is a version using only global variables and "DO loops like God meant them to be". <lang lisp>(SETQ YR 1969) (SETQ M #("JANUARY" "FEBRUARY" "MARCH" "APRIL" "MAY" "JUNE" "JULY" "AUGUST" "SEPTEMBER" "OCTOBER" "NOVEMBER" "DECEMBER")) (SETQ ML #(31 28 31 30 31 30 31 31 30 31 30 31)) (SETQ WD #("SU" "MO" "TU" "WE" "TH" "FR" "SA")) (IF (AND (= (REM YR 4) 0) (OR (/= (REM YR 100) 0) (= (REM YR 400) 0))) (VECTOR-SET! ML 1 29)) (SETQ D (REM (+ 1 (+ (* 5 (REM (- YR 1) 4)) (* 4 (REM (- YR 1) 100)) (* 6 (REM (- YR 1) 400)))) 7)) (TERPRI) (DO ((I 0 (+ I 1))) ((> I 60)) (PRINC " ")) (PRINC "SNOOPY CALENDAR ") (PRINC YR) (TERPRI) (DO ((I 0 (+ I 1))) ((> I 11)) (TERPRI) (DO ((J 0 (+ J 1))) ((> J 65)) (PRINC " ")) (PRINC (VECTOR-REF M I)) (TERPRI) (PRINC " ") (DO ((J 0 (+ J 1))) ((> J 6)) (DO ((K 0 (+ K 1))) ((> K 14)) (PRINC " ")) (PRINC (VECTOR-REF WD J)) (PRINC " ")) (TERPRI) (DO ((J 0 (+ J 1))) ((> J 6)) (IF (< J D) (DO ((K 0 (+ K 1))) ((> K 18)) (PRINC " ")))) (DO ((J 1 (+ J 1))) ((> J (VECTOR-REF ML I))) (PRINC " ") (IF (< J 10) (PRINC " ")) (DO ((K 0 (+ K 1))) ((> K 14)) (PRINC " ")) (PRINC J) (SETQ D (+ D 1)) (IF (> D 6) (TERPRI)) (IF (> D 6) (SETQ D 0))))</lang>

Output:
                                                             SNOOPY CALENDAR 1969

                                                                  JANUARY
                 SU                 MO                 TU                 WE                 TH                 FR                 SA  
                                                                           1                  2                  3                  4
                  5                  6                  7                  8                  9                 10                 11
                 12                 13                 14                 15                 16                 17                 18
                 19                 20                 21                 22                 23                 24                 25
                 26                 27                 28                 29                 30                 31
                                                                  FEBRUARY
                 SU                 MO                 TU                 WE                 TH                 FR                 SA  
                                                                                                                                    1
                  2                  3                  4                  5                  6                  7                  8
                  9                 10                 11                 12                 13                 14                 15
                 16                 17                 18                 19                 20                 21                 22
                 23                 24                 25                 26                 27                 28
                                                                  MARCH
                 SU                 MO                 TU                 WE                 TH                 FR                 SA  
                                                                                                                                    1
                  2                  3                  4                  5                  6                  7                  8
                  9                 10                 11                 12                 13                 14                 15
                 16                 17                 18                 19                 20                 21                 22
                 23                 24                 25                 26                 27                 28                 29
                 30                 31
                                                                  APRIL
                 SU                 MO                 TU                 WE                 TH                 FR                 SA  
                                                        1                  2                  3                  4                  5
                  6                  7                  8                  9                 10                 11                 12
                 13                 14                 15                 16                 17                 18                 19
                 20                 21                 22                 23                 24                 25                 26
                 27                 28                 29                 30
                                                                  MAY
                 SU                 MO                 TU                 WE                 TH                 FR                 SA  
                                                                                              1                  2                  3
                  4                  5                  6                  7                  8                  9                 10
                 11                 12                 13                 14                 15                 16                 17
                 18                 19                 20                 21                 22                 23                 24
                 25                 26                 27                 28                 29                 30                 31

                                                                  JUNE
                 SU                 MO                 TU                 WE                 TH                 FR                 SA  
                  1                  2                  3                  4                  5                  6                  7
                  8                  9                 10                 11                 12                 13                 14
                 15                 16                 17                 18                 19                 20                 21
                 22                 23                 24                 25                 26                 27                 28
                 29                 30
                                                                  JULY
                 SU                 MO                 TU                 WE                 TH                 FR                 SA  
                                                        1                  2                  3                  4                  5
                  6                  7                  8                  9                 10                 11                 12
                 13                 14                 15                 16                 17                 18                 19
                 20                 21                 22                 23                 24                 25                 26
                 27                 28                 29                 30                 31
                                                                  AUGUST
                 SU                 MO                 TU                 WE                 TH                 FR                 SA  
                                                                                                                 1                  2
                  3                  4                  5                  6                  7                  8                  9
                 10                 11                 12                 13                 14                 15                 16
                 17                 18                 19                 20                 21                 22                 23
                 24                 25                 26                 27                 28                 29                 30
                 31
                                                                  SEPTEMBER
                 SU                 MO                 TU                 WE                 TH                 FR                 SA  
                                     1                  2                  3                  4                  5                  6
                  7                  8                  9                 10                 11                 12                 13
                 14                 15                 16                 17                 18                 19                 20
                 21                 22                 23                 24                 25                 26                 27
                 28                 29                 30
                                                                  OCTOBER
                 SU                 MO                 TU                 WE                 TH                 FR                 SA  
                                                                           1                  2                  3                  4
                  5                  6                  7                  8                  9                 10                 11
                 12                 13                 14                 15                 16                 17                 18
                 19                 20                 21                 22                 23                 24                 25
                 26                 27                 28                 29                 30                 31
                                                                  NOVEMBER
                 SU                 MO                 TU                 WE                 TH                 FR                 SA  
                                                                                                                                    1
                  2                  3                  4                  5                  6                  7                  8
                  9                 10                 11                 12                 13                 14                 15
                 16                 17                 18                 19                 20                 21                 22
                 23                 24                 25                 26                 27                 28                 29
                 30
                                                                  DECEMBER
                 SU                 MO                 TU                 WE                 TH                 FR                 SA  
                                     1                  2                  3                  4                  5                  6
                  7                  8                  9                 10                 11                 12                 13
                 14                 15                 16                 17                 18                 19                 20
                 21                 22                 23                 24                 25                 26                 27
                 28                 29                 30                 31

X86 Assembly

ASSEMBLE WITH: TASM CALENDAR; TLINK /t CALENDAR

<lang asm> .MODEL TINY

       .CODE
       .486
       ORG     100H            ;.COM FILES START HERE

YEAR EQU 1969 ;DISPLAY CALENDAR FOR SPECIFIED YEAR START: MOV CX, 61 ;SPACE(61); TEXT(0, "[SNOOPY]"); CRLF(0)

       CALL    SPACE
       MOV     DX, OFFSET SNOOPY
       CALL    TEXT
       MOV     CL, 63          ;SPACE(63);  INTOUT(0, YEAR);  CRLF(0);  CRLF(0)
       CALL    SPACE
       MOV     AX, YEAR
       CALL    INTOUT
       CALL    CRLF
       CALL    CRLF
       MOV     DI, 1           ;FOR MONTH:= 1 TO 12 DO         DI=MONTH

L22: XOR SI, SI  ; FOR COL:= 0 TO 6-1 DO SI=COL L23: MOV CL, 5  ; SPACE(5)

       CALL    SPACE
       MOV     DX, DI          ;  TEXT(0, MONAME(MONTH+COL-1));  SPACE(7);
       DEC     DX              ;  DX:= (MONTH+COL-1)*10+MONAME
       ADD     DX, SI
       IMUL    DX, 10
       ADD     DX, OFFSET MONAME
       CALL    TEXT
       MOV     CL, 7
       CALL    SPACE
       CMP     SI, 5           ;  IF COL<5 THEN SPACE(1);
       JGE     L24
        MOV    CL, 1
        CALL   SPACE
        INC    SI
        JMP    L23

L24: CALL CRLF

       MOV     SI, 6           ; FOR COL:= 0 TO 6-1 DO

L25: MOV DX, OFFSET SUMO ; TEXT(0, "SU MO TU WE TH FR SA");

       CALL    TEXT
       DEC     SI              ;   IF COL<5 THEN SPACE(2);
       JE      L27
        MOV    CL, 2
        CALL   SPACE
        JMP    L25

L27: CALL CRLF

       XOR     SI, SI          ;FOR COL:= 0 TO 6-1 DO

L28: MOV BX, DI ;DAY OF FIRST SUNDAY OF MONTH (CAN BE NEGATIVE)

       ADD     BX, SI          ;DAY(COL):= 1 - WEEKDAY(YEAR, MONTH+COL, 1);
       MOV     BP, YEAR
DAY OF WEEK FOR FIRST DAY OF THE MONTH (0=SUN 1=MON..6=SAT)
       CMP     BL, 2           ;IF MONTH<=2 THEN
       JG      L3
        ADD    BL, 12          ; MONTH:= MONTH+12;
        DEC    BP              ; YEAR:= YEAR-1;

L3:

REM((1-1 + (MONTH+1)*26/10 + YEAR + YEAR/4 + YEAR/100*6 + YEAR/400)/7)
       INC     BX              ;MONTH
       IMUL    AX, BX, 26
       MOV     CL, 10
       CWD
       IDIV    CX
       MOV     BX, AX
       MOV     AX, BP          ;YEAR
       ADD     BX, AX
       SHR     AX, 2
       ADD     BX, AX
       MOV     CL, 25
       CWD
       IDIV    CX
       IMUL    DX, AX, 6       ;YEAR/100*6
       ADD     BX, DX
       SHR     AX, 2           ;YEAR/400
       ADD     AX, BX
       MOV     CL, 7
       CWD
       IDIV    CX
       NEG     DX
       INC     DX
       MOV     [SI+DAY], DL    ;COL+DAY
       INC     SI
       CMP     SI, 5
       JLE     L28
       MOV     BP, 6           ;FOR LINE:= 0 TO 6-1 DO         BP=LINE

L29: XOR SI, SI  ; FOR COL:= 0 TO 6-1 DO SI=COL L30: MOV BX, DI  ; DAYMAX:= DAYS(MONTH+COL);

       MOV     BL, [BX+SI+DAYS]
IF MONTH+COL=2 & (REM(YEAR/4)=0 & REM(YEAR/100)#0 ! REM(YEAR/400)=0) THEN
       MOV     AX, DI          ;MONTH
       ADD     AX, SI
       CMP     AL, 2
       JNE     L32
       MOV     AX, YEAR
       TEST    AL, 03H
       JNE     L32
       MOV     CL,100
       CWD
       IDIV    CX
       TEST    DX, DX
       JNE     L31
       TEST    AL, 03H
       JNE     L32

L31: INC BX ;IF FEBRUARY AND LEAP YEAR THEN ADD A DAY L32:

       MOV     DX, 7           ;FOR WEEKDAY:= 0 TO 7-1 DO

L33: MOVZX AX, [SI+DAY]  ; IF DAY(COL)>=1 & DAY(COL)<=DAYMAX THEN

       CMP     AL, 1
       JL      L34
       CMP     AL, BL
       JG      L34
       CALL    INTOUT          ; INTOUT(0, DAY(COL));
       CMP     AL, 10          ; IF DAY(COL)<10 THEN SPACE(1); LEFT JUSTIFY
       JGE     L36
        MOV    CL, 1
        CALL   SPACE
       JMP     L36

L34: MOV CL, 2  ; ELSE SPACE(2);

       CALL    SPACE           ; SUPPRESS OUT OF RANGE DAYS

L36: MOV CL, 1  ; SPACE(1);

       CALL    SPACE
       INC     BYTE PTR [SI+DAY] ; DAY(COL):= DAY(COL)+1;
       DEC     DX              ;NEXT WEEKDAY
       JNE     L33
       CMP     SI, 5           ;IF COL<5 THEN SPACE(1);
       JGE     L37
        MOV    CL, 1
        CALL   SPACE
        INC    SI
        JMP    L30

L37: CALL CRLF

       DEC     BP              ;NEXT LINE DOWN
       JNE     L29
       CALL    CRLF
       ADD     DI, 6           ;NEXT 6 MONTHS
       CMP     DI, 12
       JLE     L22
       RET
DISPLAY POSITIVE INTEGER IN AX

INTOUT: PUSHA

       MOV     BX, 10
       XOR     CX, CX

NO10: CWD

       IDIV    BX
       PUSH    DX
       INC     CX
       TEST    AX, AX
       JNE     NO10

NO20: MOV AH, 02H

       POP     DX
       ADD     DL, '0'
       INT     21H
       LOOP    NO20
       POPA
       RET
DISPLAY CX SPACE CHARACTERS

SPACE: PUSHA SP10: MOV AH, 02H

       MOV     DL, 20H
       INT     21H
       LOOP    SP10
       POPA
       RET
START A NEW LINE

CRLF: MOV DX, OFFSET LCRLF

DISPLAY STRING AT DX

TEXT: MOV AH, 09H

       INT     21H
       RET

SNOOPY DB "[SNOOPY]" LCRLF DB 0DH, 0AH, '$' MONAME DB " JANUARY $ FEBRUARY$ MARCH $ APRIL $ MAY $ JUNE $"

       DB      "   JULY  $  AUGUST $SEPTEMBER$  OCTOBER$ NOVEMBER$ DECEMBER$"

SUMO DB "SU MO TU WE TH FR SA$" DAYS DB 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 DAY DB  ?, ?, ?, ?, ?, ?

       END     START</lang>
Output:
                                                             [SNOOPY]
                                                               1969

      JANUARY               FEBRUARY               MARCH                 APRIL                  MAY                   JUNE         
SU MO TU WE TH FR SA  SU MO TU WE TH FR SA  SU MO TU WE TH FR SA  SU MO TU WE TH FR SA  SU MO TU WE TH FR SA  SU MO TU WE TH FR SA
         1  2  3  4                     1                     1         1  2  3  4  5               1  2  3   1  2  3  4  5  6  7  
5  6  7  8  9  10 11  2  3  4  5  6  7  8   2  3  4  5  6  7  8   6  7  8  9  10 11 12  4  5  6  7  8  9  10  8  9  10 11 12 13 14 
12 13 14 15 16 17 18  9  10 11 12 13 14 15  9  10 11 12 13 14 15  13 14 15 16 17 18 19  11 12 13 14 15 16 17  15 16 17 18 19 20 21 
19 20 21 22 23 24 25  16 17 18 19 20 21 22  16 17 18 19 20 21 22  20 21 22 23 24 25 26  18 19 20 21 22 23 24  22 23 24 25 26 27 28 
26 27 28 29 30 31     23 24 25 26 27 28     23 24 25 26 27 28 29  27 28 29 30           25 26 27 28 29 30 31  29 30                
                                            30 31                                                                                  

        JULY                 AUGUST              SEPTEMBER               OCTOBER              NOVEMBER              DECEMBER       
SU MO TU WE TH FR SA  SU MO TU WE TH FR SA  SU MO TU WE TH FR SA  SU MO TU WE TH FR SA  SU MO TU WE TH FR SA  SU MO TU WE TH FR SA
      1  2  3  4  5                  1  2      1  2  3  4  5  6            1  2  3  4                     1      1  2  3  4  5  6  
6  7  8  9  10 11 12  3  4  5  6  7  8  9   7  8  9  10 11 12 13  5  6  7  8  9  10 11  2  3  4  5  6  7  8   7  8  9  10 11 12 13 
13 14 15 16 17 18 19  10 11 12 13 14 15 16  14 15 16 17 18 19 20  12 13 14 15 16 17 18  9  10 11 12 13 14 15  14 15 16 17 18 19 20 
20 21 22 23 24 25 26  17 18 19 20 21 22 23  21 22 23 24 25 26 27  19 20 21 22 23 24 25  16 17 18 19 20 21 22  21 22 23 24 25 26 27 
27 28 29 30 31        24 25 26 27 28 29 30  28 29 30              26 27 28 29 30 31     23 24 25 26 27 28 29  28 29 30 31          
                      31                                                                30                                         

zkl

Translation of: D

Using a large helping of grease, in the form of a pre-processor.

The calendar code, file UPCAL.zkl (upper cased version of Calendar#zkl): <lang zkl>VAR [CONST] D=TIME.DATE, DAYS="SU MO TU WE TH FR SA";

FCN CENTER(TEXT,M) { STRING(" "*((M-TEXT.LEN())/2),TEXT) }

FCN ONEMONTH(YEAR,MONTH){

  DAY1:=D.ZELLER(YEAR,MONTH,1);    //1969-1-1 -->3 (WED, ISO 8601)
  DAYZ:=D.DAYSINMONTH(YEAR,MONTH); //1969-1   -->31
  LIST(CENTER(D.MONTHNAMES[MONTH],DAYS.LEN()),DAYS).EXTEND(
     (1).PUMP(DAYZ,(0).PUMP(DAY1,LIST,T(VOID,""))).APPLY("%2S ".FMT)
     .PUMP(LIST,T(VOID.READ,DAYS.LEN()/3,FALSE),STRING.CREATE));

} ...</lang> And the pre-processor, hand rolled for the above code (file bbb.zkl): <lang zkl>code:=File(vm.arglist[0]).read(); code=Data(Void,code.text.toLower()); mixed:=T("string","String", "list","List", " t("," T(",",t(",",T(",

  ".tostring",".toString", "void.read","Void.Read",
  "time.date","Time.Date", "utils.","Utils.", "zipwith","zipWith",
  "daysinmonth","daysInMonth", "monthnames","monthNames",
  "void","Void", "false","False",
  "d.october","d.October", 

); mixed.pump(Void,Void.Read,'wrap(up,down){ code.replace(up,down) }); Compiler.Compiler.compileText(code)();</lang>

Output:
$ zkl bbb UPCAL.zkl
                       3 days of peace & music
                                 1969

      January                  February                  March             
su mo tu we th fr sa     su mo tu we th fr sa     su mo tu we th fr sa     
          1  2  3  4                        1                        1     
 5  6  7  8  9 10 11      2  3  4  5  6  7  8      2  3  4  5  6  7  8    
...