Category : C++ Source Code
Archive   : VCCRT1.ZIP
Filename : STRFTIME.C

 
Output of file : STRFTIME.C contained in archive : VCCRT1.ZIP
/***
*strftime.c - String Format Time
*
* Copyright (c) 1988-1992, Microsoft Corporation. All rights reserved.
*
*Purpose:
*
*******************************************************************************/

#include
#include
#include

/* Prototypes for local routines */
static void near pascal _store_str (char *in, char **out, size_t *count);
static void near pascal _store_num (int num, int digits, char **out, size_t *count);
static void near pascal _store_time (const struct tm *tmptr, char **out, size_t *count);
static void near pascal _store_date (const struct tm *tmptr, char **out, size_t *count);



/* Length of the date and time representation strings. [In the future,
these values may appear in the locale-specific structure.] */

#define _DATE_LENGTH 8 /* mm-dd-yy (null not included) */
#define _TIME_LENGTH 8 /* hh:mm:ss (null not included) */


/* Define the max length for each string type including space for a null. */


#define _MAX_WDAY_ABBR 4
#define _MAX_WDAY 10
#define _MAX_MONTH_ABBR 4
#define _MAX_MONTH 10
#define _MAX_AMPM 3


/* LC_TIME localization structure */

struct _lc_time_data {
char wday_abbr[7][_MAX_WDAY_ABBR];
char wday[7][_MAX_WDAY];
char month_abbr[12][_MAX_MONTH_ABBR];
char month[12][_MAX_MONTH];
char ampm[2][_MAX_AMPM];
};


/* LC_TIME data for local "C" */

struct _lc_time_data _lc_time_c = {

{"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"},

{"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
"Friday", "Saturday", },

{"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug",
"Sep", "Oct", "Nov", "Dec"},

{"January", "February", "March", "April", "May", "June",
"July", "August", "September", "October",
"November", "December"},

{"AM", "PM"}

};


/* Pointer to the current LC_TIME data structure. */

struct _lc_time_data *_lc_time_curr = &_lc_time_c;


/***
*size_t strftime(string, maxsize, format, timeptr) - Format a time string
*
*Purpose:
* Place characters into the user's output buffer expanding time
* format directives as described in the user's control string.
* Use the supplied 'tm' structure for time data when expanding
* the format directives.
* [ANSI]
*
*Entry:
* char *string = pointer to output string
* size_t maxsize = max length of string
* const char *format = format control string
* const struct tm *timeptr = pointer to tb data structure
*
*Exit:
* !0 = If the total number of resulting characters including the
* terminating null is not more than 'maxsize', then return the
* number of chars placed in the 'string' array (not including the
* null terminator).
*
* 0 = Otherwise, return 0 and the contents of the string are
* indeterminate.
*
*Exceptions:
*
*******************************************************************************/

size_t strftime(string, maxsize, format, timeptr)
char *string;
size_t maxsize;
const char *format;
const struct tm *timeptr;
{

struct _lc_time_data *lc_time; /* lc_time data pointer */
size_t left; /* space left in output string */
unsigned temp; /* temps */
int wdaytemp;


/* Copy maxsize into temp. */

left = maxsize;

/* Get a copy of the current _lc_time_data pointer. This
should prevent the necessity of locking/unlocking in mthread
code (if we can guarrentee that the various _lc_time data
structures are always in the same segment). */

lc_time = _lc_time_curr;

/* Copy the input string to the output string expanding the format
designations appropriately. Stop copying when one of the following
is true: (1) we hit a null char in the input stream, or (2) there's
no room left in the output stream. */

while (left > 0)
switch(*format) {

case('\0'):

/* end of format input string */
goto done;

case('%'):

/* Format directive. Take appropriate action based
on format control character. */

format++; /* skip over % char */
switch(*format++) { /* switch on format char */

case('a'): /* abbreviated weekday name */
_store_str(lc_time->wday_abbr[timeptr->tm_wday],
&string, &left);
break;

case('A'): /* full weekday name */
_store_str(lc_time->wday[timeptr->tm_wday],
&string, &left);
break;

case('b'): /* abbreviated month name */
_store_str(lc_time->month_abbr[timeptr->tm_mon],
&string, &left);
break;

case('B'): /* full month name */
_store_str(lc_time->month[timeptr->tm_mon],
&string, &left);
break;

case('c'): /* date and time display */
if ((_DATE_LENGTH+_TIME_LENGTH+1) < left) {
_store_date(timeptr, &string, &left);
*string++=' '; left--;
_store_time(timeptr, &string, &left);
}
else
left=0;
break;

case('d'): /* mday in decimal (01-31) */
_store_num(timeptr->tm_mday, 2, &string, &left);
break;

case('H'): /* 24-hour decimal (00-23) */
_store_num(timeptr->tm_hour, 2, &string, &left);
break;

case('I'): /* 12-hour decimal (01-12) */
if (!(temp = timeptr->tm_hour%12))
temp=12;
_store_num(temp, 2, &string, &left);
break;

case('j'): /* yday in decimal (001-366) */
_store_num(timeptr->tm_yday+1, 3, &string, &left);
break;

case('m'): /* month in decimal (01-12) */
_store_num(timeptr->tm_mon+1, 2, &string, &left);
break;

case('M'): /* minute in decimal (00-59) */
_store_num(timeptr->tm_min, 2, &string, &left);
break;

case('p'): /* AM/PM designation */
if (timeptr->tm_hour <= 11)
_store_str(lc_time->ampm[0], &string, &left);
else
_store_str(lc_time->ampm[1], &string, &left);
break;

case('S'): /* secs in decimal (00-59) */
_store_num(timeptr->tm_sec, 2, &string, &left);
break;

case('U'): /* sunday week number (00-53) */
wdaytemp = timeptr->tm_wday;
goto weeknum; /* join common code */

case('w'): /* week day in decimal (0-6) */
_store_num(timeptr->tm_wday, 1, &string, &left);
break;

case('W'): /* monday week number (00-53) */
if (timeptr->tm_wday == 0) /* monday based */
wdaytemp = 6;
else
wdaytemp = timeptr->tm_wday-1;
weeknum:
if (timeptr->tm_yday < wdaytemp)
temp=0;
else {
temp = timeptr->tm_yday/7;
if ((timeptr->tm_yday%7) >= wdaytemp)
temp++;
}
_store_num(temp, 2, &string, &left);
break;

case('x'): /* date display */
_store_date(timeptr, &string, &left);
break;

case('X'): /* time display */
_store_time(timeptr, &string, &left);
break;

case('y'): /* year w/o century (00-99) */
temp = timeptr->tm_year%100;
_store_num(temp, 2, &string, &left);
break;

case('Y'): /* year w/ century */
temp = (((timeptr->tm_year/100)+19)*100) +
(timeptr->tm_year%100);
_store_num(temp, 4, &string, &left);
break;

case('z'): /* time zone name, if any */
case('Z'): /* ANSI specifies 'Z', also support 'z' */
__tzset(); /* set up tz info */
_store_str(_tzname[((timeptr->tm_isdst)?1:0)],
&string, &left);
break;

case('%'): /* percent sign */
*string++ = '%';
left--;
break;

default: /* unknown format directive */
/* ignore the directive and continue */
/* [ANSI: Behavior is undefined.] */
break;

} /* end % switch */

break;


default:

/* store character, bump pointers, dec the char count */
*string++ = *format++;
left--;
break;
}


/* All done. See if we terminated because we hit a null char or because
we ran out of space */

done:

if (left > 0) {

/* Store a terminating null char and return the number of chars
we stored in the output string. */

*string = '\0';
return(maxsize-left);
}

else
return(0);

}


/***
*_store_str() - Copy a time string
*
*Purpose:
* Copy the supplied time string into the output string until
* (1) we hit a null in the time string, or (2) the given count
* goes to 0.
*
* *** For internal use with strftime() only ***
*
*Entry:
* char *in = pointer to null terminated time string
* char **out = address of pointer to output string
* size_t *count = address of char count (space in output area)
*
*Exit:
* none
*Exceptions:
*
*******************************************************************************/

static void near pascal _store_str (in, out, count)
char *in;
char **out;
size_t *count;
{

while ((*count > 0) && (*in != '\0')) {
*(*out)++ = *in++;
(*count)--;
}
}


/***
*_store_num() - Convert a number to ascii and copy it
*
*Purpose:
* Convert the supplied number to decimal and store
* in the output buffer. Update both the count and
* buffer pointers.
*
* *** For internal use with strftime() only ***
*
*Entry:
* int num = integer value
* int digits = # of ascii digits to put into string
* char **out = address of pointer to output string
* size_t *count = address of char count (space in output area)
*
*Exit:
* none
*Exceptions:
*
*******************************************************************************/

static void near pascal _store_num (num, digits, out, count)
int num;
int digits;
char **out;
size_t *count;
{
int temp=0;

if ((size_t)digits < *count) {
for (digits--; (digits+1); digits--) {
(*out)[digits] = (char)('0' + num % 10);
num /= 10;
temp++;
}
*out += temp;
*count -= temp;
}
else
*count = 0;
}


/***
*_store_time() - Store time in appropriate format
*
*Purpose:
* Format the time in the current locale's format
* and store it in the supplied buffer.
*
* [*** Currently, this routine assumes standard "C"
* locale. When full localization support is introduced,
* this functionality will have to be expanded.]
*
* Standard "C" locale time format:
*
* hh:mm:ss
*
* *** For internal use with strftime() only ***
*
*Entry:
*
* const struct tm *tmptr = pointer to time/date structure
* char **out = address of pointer to output string
* size_t *count = address of char count (space in output area)
*
*Exit:
* none
*Exceptions:
*
*******************************************************************************/

static void near pascal _store_time (tmptr, out, count)
const struct tm *tmptr;
char **out;
size_t *count;
{

if (_TIME_LENGTH < *count) {

_store_num(tmptr->tm_hour, 2, out, count);
*(*out)++ = ':';
_store_num(tmptr->tm_min, 2, out, count);
*(*out)++ = ':';
_store_num(tmptr->tm_sec, 2, out, count);

*count -= 2; /* count the colons */
}

else
*count = 0;

}


/***
*_store_date() - Store date in appropriate format
*
*Purpose:
* Format the date in the current locale's format
* and store it in the supplied buffer.
*
* [*** Currently, this routine assumes standard "C"
* locale. When full localization support is introduced,
* this functionality will have to be expanded.]
*
* Standard "C" locale date format:
*
* mm/dd/yy
*
* *** For internal use with strftime() only ***
*
*Entry:
*
* const struct tm *tmptr = pointer to time/date structure
* char **out = address of pointer to output string
* size_t *count = address of char count (space in output area)
*
*Exit:
* none
*Exceptions:
*
*******************************************************************************/

static void near pascal _store_date (tmptr, out, count)
const struct tm *tmptr;
char **out;
size_t *count;
{

if (_DATE_LENGTH < *count) {

_store_num(tmptr->tm_mon+1, 2, out, count);
*(*out)++ = '/';
_store_num(tmptr->tm_mday, 2, out, count);
*(*out)++ = '/';
_store_num(tmptr->tm_year%100, 2, out, count);

*count -= 2; /* count the backslashes */
}

else
*count = 0;

}


  3 Responses to “Category : C++ Source Code
Archive   : VCCRT1.ZIP
Filename : STRFTIME.C

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/