/* Copyright (c) 1991 Raymond Hettinger. All rights reserved. */ typedef unsigned short YEAR; typedef unsigned short DOY; typedef enum { jan=0, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec } MONTH; typedef unsigned char DOM; typedef enum { sun=0, mon, tue, wed, thr, fri, sat } DOW; typedef DOM (*calform)[6][7]; struct request{ YEAR year; MONTH month; }; struct request *inputAcquisition( int argc, char *argv[] ); calform gridBuilder( YEAR, MONTH ); void outputOne( const YEAR, const MONTH ); void outputTwelve( const YEAR ); #include #include #include #include /* Buffer size selected to hold entire output */ #define BUFFERSIZE 2048 char stdoutBuffer[ BUFFERSIZE ]; int cdecl main( int argc, char *argv[] ) { struct request *task; /* Highspeed buffered output */ setvbuf( stdout, stdoutBuffer, _IOFBF, BUFFERSIZE ); setmode( fileno( stdout ), O_BINARY ); task = inputAcquisition( argc, argv ); if( task->month ) outputOne( task->year, task->month-1 ); else outputTwelve( task->year ); return 0; } struct request * inputAcquisition( int argc, char *argv[] ) { struct request *goal = malloc( sizeof(struct request ) ); if( argc == 2 ){ goal->year = (YEAR)atoi( argv[1] ); goal->month = 0; /* Zero dictates a full year print */ }else if( argc == 3 ){ goal->year = (YEAR)atoi( argv[2] ); goal->month = (MONTH)atoi( argv[1] ); if( goal->month < 1 || goal->month > 12 ){ puts( "Bad argument." ); exit( 2 ); } }else{ puts( "usage: cal [month] year." ); puts( "Copyright (c) 1991 Raymond Hettinger. All rights reserved." ); exit(3); } if( goal->year < 1 || goal->year > 9999 ){ /* The year %d is outside the normal range (1 to 9999). */ puts( "Bad argument." ); exit( 1 ); } return goal; } /* Module provides a single function interface generating a one month calendar grid. Returns a pointer to a 2-D array corresponding to a normal calendar presentation ( viz. monthGrid[ weekNumber ][ dayOfWeek ]. The elements of the array are days-of-month (ranging from 1 to 31 ) or a zero to indicate a blank. The dayOfWeek index starts from Sunday (zero index) and ends at Saturday (index six). The weekNumber is the row on a calendar print-out and is also zero-offset. */ const DOY cumMon[2][ 12 ] = { { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }, { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 } }; const DOM lenMon[2][12] = { { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } }; const DOM jul2greg[6][7] = { { 00, 00, 01, 02, 14, 15, 16 }, { 17, 18, 19, 20, 21, 22, 23 }, { 24, 25, 26, 27, 28, 29, 30 }, { 00, 00, 00, 00, 00, 00, 00 }, { 00, 00, 00, 00, 00, 00, 00 }, { 00, 00, 00, 00, 00, 00, 00 }, }; calform gridBuilder( YEAR y, MONTH m ) { DOM i, *curr; calform grid = (calform)calloc( 42, sizeof(DOM) ); DOY d = y; char ly = 1; if( grid == NULL ){ puts( "Unable to allocate memory." ); exit(3); } if( y==1752 && m==8 ){ return (calform)&jul2greg; }else if( (y>1752) || ( (y==1752) & (m>8) ) ){ if( y & 0x3 ) ly=0; else if( y % 100 ) ly=1; else if( y % 400 ) ly=0; d += ( y / 400 ) - ( y / 100 ); }else{ if( y & 0x3 ) ly=0; d += 5; } d += cumMon[ly][m] + ( y >> 2 ) - ly; d %= 7; for( i=1, curr=((DOM*)(*grid))+d ; i<=lenMon[ly][m] ; i++, curr++ ) *curr = i; return grid; } #define TAB 9 #define SPACE 32 void putstr( const char * ); char * YEARtoa( YEAR ); const char * weekHeader = { " S M Tu W Th F S\t" }; const char * monthStr[12] = { { "January" }, { "February" }, { "March" }, { "April" }, { "May" }, { "June" }, { "July" }, { "August" }, { "September" }, { "October" }, { "November" }, { "December" } }; const char * blockStr[4] = { { "\tJan\t\t\tFeb\t\t\tMar\r" }, { "\tApr\t\t\tMay\t\t\tJun\r" }, { "\tJul\t\t\tAug\t\t\tSep\r"}, { "\tOct\t\t\tNov\t\t\tDec\r" } }; const char * dayStr[32] = { { " " }, { " 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 " } }; void outputOne( const YEAR y, const MONTH m ) { short row; DOW day; calform grid = gridBuilder( y, m ); putstr( " " ); putstr( monthStr[m] ); putchar( SPACE ); putstr( YEARtoa( y ) ); puts( "\r" ); putstr( weekHeader ); puts( "\r" ); for( row=0 ; row<6 ; row++ ){ for( day=sun ; day<=sat ; day++ ) putstr( dayStr[ (*grid)[row][day] ] ); puts( "\r" ); } } void outputTwelve( const YEAR y ) { short row, block, col; calform grid[3]; DOW day; MONTH m=0; putstr( "\t\t\t\t" ); puts( YEARtoa( y ) ); puts( "\r" ); for( block=0 ; block<4 ; block++ ){ puts( blockStr[block] ); putstr( weekHeader ); putstr( weekHeader ); putstr( weekHeader ); puts( "\r" ); for( col=0 ; col<3 ; col++ ) grid[col] = gridBuilder( y, m++ ); for( row=0 ; row<6 ; row++ ){ for( col=0 ; col<3 ; col++ ){ for( day=sun ; day<=sat ; day++ ) putstr( dayStr[ (*grid[col])[row][day] ] ); putchar( TAB ); } puts( "\r" ); } puts( "\r" ); } } void putstr( const char *str ) { while( *str ) putchar( *(str++) ); } char * YEARtoa( YEAR y ) { char *buff = (char *)malloc( 10 ); char *last = buff+9; *(last) = 0; do{ *( --last ) = (char)'0' + (char)(y % 10); y /= 10; }while( y ); return last; }