[comp.lang.c] Microsoft C 5.1 question

mcintyre@turing.cs.rpi.edu (David McIntyre) (01/14/89)

I am having a little trouble with C, and am hoping that someone has
already conquered this problem:

	I am using _dos_findfirst and _dos_findnext to get information
about directory entries.

	The time and date stamps on the file are returned
as unsigneds (wr_time and wr_date).  

	I would like to extract the information about date and time
from these unsigneds, but the time and date conversion functions
do not seem to take similar values.

	Could someone give me 2 or 3 sample lines of code showing
how to print these unsigned dates and times as xx:xx:xx and xx/xx/xxxx
values?

		Thanks,
		  Dave


Dave "mr question" McIntyre     |      "....say you're thinking about a plate
mcintyre@turing.cs.rpi.edu      |       of shrimp.....and someone says to 
office : 518-276-8633		|	you `plate,' or `shrimp'......"
home   : 518-271-6664		|

furlani@broadway.UUCP (John L. Furlani) (01/15/89)

In article <104@rpi.edu>, mcintyre@turing.cs.rpi.edu (David McIntyre) writes:
> 
> 	Could someone give me 2 or 3 sample lines of code showing
> how to print these unsigned dates and times as xx:xx:xx and xx/xx/xxxx
> values?
> 

Here are two functions that do just that when passed the date and time,
respectively.  It should be noted that since DOS stores file times acurate
only to 2 second intervals, seconds are usually left off.  I recommend
looking into purchasing The Waite Group's Microsoft C Bible.  It has all
the 5.1 functions will full usage, compatability, example codes, other
book references for more information on a particular subject, and more.  
I hope these help.

print_sysdate (int date)
{
    unsigned day         = (date & 0x1f);
    unsigned month       = (date >> 5) & 0xf;
    unsigned year        = (date >> 9) & 0x7f;

    printf("%2d/%2d/%2d", day, month, (year + 80));
}

print_systime(int time)
{
    char min_str[5];
    char sec_str[5];
    unsigned second   = (time & 0x1f) * 2;
    unsigned minute   = (time >>  5) & 0x3f;
    unsigned hour     = (time >> 11) & 0x1f;

    if(minute < 10)
        sprintf(min_str, "0%d", minute);
    else
        sprintf(min_str, "%d", minute);

    if(second < 10)
        sprintf(sec_str, "0%d", second);
    else
        sprintf(sec_str, "%d", second);

    printf("%2d:%s:%s", hour, min_str, sec_str);
}

____________
Disclaimer:  "Just blame Me, Myself, and I for it."
John L. Furlani 
The University of South Carolina, Columbia SC
(...!uunet!ncrlnk!ncrcae!broadway!furlani)

ka@june.cs.washington.edu (Kenneth Almquist) (01/16/89)

]    if(minute < 10)
]        sprintf(min_str, "0%d", minute);
]    else
]        sprintf(min_str, "%d", minute);
]
]    if(second < 10)
]        sprintf(sec_str, "0%d", second);
]    else
]        sprintf(sec_str, "%d", second);
]
]    printf("%2d:%s:%s", hour, min_str, sec_str);

This can be shortened to

     printf("%2d:%.2d:%.2d", hour, minute, second);

A "." introduces a precision, which specifies the minimum number of
digits to print.
				Kenneth Almquist

abcscnge@csuna.UUCP (Scott "The Pseudo-Hacker" Neugroschl) (01/22/89)

In article <6951@june.cs.washington.edu> ka@june.cs.washington.edu (Kenneth Almquist) writes:
]]    if(minute < 10)
]]        sprintf(min_str, "0%d", minute);
]]    else
]]        sprintf(min_str, "%d", minute);
]]
]]    if(second < 10)
]]        sprintf(sec_str, "0%d", second);
]]    else
]]        sprintf(sec_str, "%d", second);
]]
]]    printf("%2d:%s:%s", hour, min_str, sec_str);
]
]This can be shortened to
]
]     printf("%2d:%.2d:%.2d", hour, minute, second);
]
]				Kenneth Almquist


How about
     printf("%2d:%02d:%02d", hour, minute, second);

K&R (page 146) specify that the 0 is the pad character to pad out the
2 digit integer in this case.  Seems to solve all the problems. 


-- 
Scott "The Pseudo-Hacker" Neugroschl
UUCP:  ...!sm.unisys.com!csun!csuna!abcscnge
-- "Beat me, whip me, make me code in Ada"
-- Disclaimers?  We don't need no stinking disclaimers!!!

ka@june.cs.washington.edu (Kenneth Almquist) (01/22/89)

abcscnge@csuna.UUCP (Scott "The Pseudo-Hacker" Neugroschl) writes:
> In article <6951@june.cs.washington.edu> ka@june.cs.washington.edu (Kenneth Almquist) writes:
> ]    printf("%2d:%.2d:%.2d", hour, minute, second);
> 
> How about
>      printf("%2d:%02d:%02d", hour, minute, second);

These behave identically.  A fair number of years ago, AT&T decided to
switch from the "%02d" format to the "%.2d" format.  A couple of reasons
for this may be:

     1) Conceptual simplicity.  The printf format has a precision field
	for use by the %s and the floating point formats; it makes sense
	to use this same field for integer formats rather than ignoring
	the precision and using some other method of getting zero padding.

     2) Flexibility.  Using the precision to specify the zero padding
	allows the field width to be used for its normal function even
	when zero padding is desired.

The "%02d" format will no doubt continue to work forever.  I've switched
to the new format because I don't expect newcomers to the C world want to
learn all the obsolete features of the language.
				Kenneth Almquist

ark@alice.UUCP (Andrew Koenig) (01/23/89)

In article <7026@june.cs.washington.edu>, ka@june.cs.washington.edu (Kenneth Almquist) writes:
> abcscnge@csuna.UUCP (Scott "The Pseudo-Hacker" Neugroschl) writes:
> > In article <6951@june.cs.washington.edu> ka@june.cs.washington.edu (Kenneth Almquist) writes:
> > ]    printf("%2d:%.2d:%.2d", hour, minute, second);
> > 
> > How about
> >      printf("%2d:%02d:%02d", hour, minute, second);
> 
> These behave identically.  A fair number of years ago, AT&T decided to
> switch from the "%02d" format to the "%.2d" format.

Actually, they behave identically only for positive numbers.

The change came about for several reasons, not all of which
I remember.  One was a desire to be able to print things like
0x00076552, which just didn't fit into the notion of zero-padding.
Another was that `zero-padding' didn't really describe the operation.
After all, if you zero-pad -3 to six characters, you should get
0000-3, right?  Some head-scratching and a lot of discussion
later, we decided that the operation we really wanted was
`guarantee at least a particular number of digits' and that
that should be done as part of conversion, not as part of padding.
-- 
				--Andrew Koenig
				  ark@europa.att.com

mfinegan@uceng.UC.EDU (michael k finegan) (01/26/89)

I have been having a problem with far pointer conversion in MSC 5.1, using
the medium memory model. It goes like this: in medium model code pointers
are 32 bits, while data pointers are 16 bits. There is an exception to the
data pointer size, and that is done using the keyword far.
    What I am trying to do is put an address into a far data pointer
(unsigned char far * ptr), which works okay at first, but when the global
pointer gets accessed in a subroutine, low and behold - it is different! It
appears that the high order word is zeroed out ... My question: has anyone out
there in net land put addresses into far pointers in medium model with success?
Is there a trick?
 The people at MSC claim it should work, but they haven't tried to code it ...

(By the way - I am using buildptr(segment,offset) from the LIM specs. to 
instantiate the pointers: the far pointer is treated as an unsigned long, and
the segment is shifted left 16 and added to the offset to create the far ptr)
				Thanks,
					Mike Finegan
					mfinegan@uceng.uc.edu
				

seg@smsdpg.uu.net (Scott Garfinkle) (01/27/89)

From article <617@uceng.UC.EDU>, by mfinegan@uceng.UC.EDU (michael k finegan):
>     What I am trying to do is put an address into a far data pointer
> (unsigned char far * ptr), which works okay at first, but when the global
> pointer gets accessed in a subroutine, low and behold - it is different! It
> appears that the high order word is zeroed out ... My question: has anyone out
> there in net land put addresses into far pointers in medium model with success?
> Is there a trick?

No.  I've done it.  It works.  It's just a real pain.
Following code to set an arbitrary string in the DOS environment works
in all models:
		Scott E. Garfinkle
		SMS Data Products Group, Inc.
		uunet!smsdpg!seg (seg@smsdpg.uu.net)

----------
/* Demo of how to set a string in parent environment. 
 * By Scott E. Garfinkle  -- No rights reserved, no responsibility assumed.
 *
 * This program can be very unhealthy for your environment.  In particular,
 * it does not do the following:
 *		1.  Check for theoretically illegal characters, like '=' in the
 *			  environment.
 *		2.  Remove old definitions that you're redefining.
 *		3.  Check to see if you've hit the limit of the environment size.
 *		4.  Force the new variable into uppercase.
 * Some of the above aren't bugs, depending on your point of view.  If you
 * don't like something, change it.
 */
#include <stdio.h>

extern unsigned _psp;	/* set to segment of our psp by MSC init routines */

/* from dos.h */
#define FP_SEG(fp) (*((unsigned *)&(fp) + 1))
#define FP_OFF(fp) (*((unsigned *)&(fp)))

main(int argc, char **argv)
{
	char far *env_ptr;
	int count;
	unsigned far *psp_ptr;
	extern char *getenv(const char *);

	if(argc != 3) {
	 	fprintf(stderr,"Usage: %s <variable> <value>\n", *argv);
		exit(1);
	}
	psp_ptr = (unsigned far *) (((long) _psp << 16 ) + 0x16L);
	/* now psp_ptr points to DOS PSP segment */
	psp_ptr = (unsigned far *) (((long) *psp_ptr << 16 ) + 0x2cL);
	/* now psp_ptr points to DOS environ segment */
	env_ptr = (char far *) ((long) *psp_ptr << 16 );
	/* now env_ptr points to DOS environ */
	while(*env_ptr)	/* skip past the current strings */
		env_ptr += strlen(env_ptr)+1;
	/* usually, sprintf returns number of characters written, excluding
	 * the null.  This is true, e.g. for msc.
	 */
#ifndef SPRINTF_RETURNS_CHAR
	{
		int count;
		char buffer[512]; /* arbitrary */

		count = sprintf(buffer,"%s=%s",argv[1],argv[2]);
		movedata(	/* of course microsoft does this backwards */
				(unsigned) (( (long) (char far *) buffer) >> 16),	/* yech */
				(unsigned) buffer,
				FP_SEG(env_ptr), FP_OFF(env_ptr),
				++count
			);
		env_ptr[count] = '\0';
	}
#else
	(void) sprintf(env_ptr,"%s=%s",argv[1],argv[2]);
	env_ptr[strlen(env_ptr)+1] = '\0';	/* need two nulls to terminate env */
#endif
	exit(0);
}

allbery@ncoast.ORG (Brandon S. Allbery) (01/29/89)

As quoted from <7026@june.cs.washington.edu> by ka@june.cs.washington.edu (Kenneth Almquist):
+---------------
| These behave identically.  A fair number of years ago, AT&T decided to
| switch from the "%02d" format to the "%.2d" format.  A couple of reasons
| for this may be:
| 
|      1) Conceptual simplicity.  The printf format has a precision field
| 	for use by the %s and the floating point formats; it makes sense
| 	to use this same field for integer formats rather than ignoring
| 	the precision and using some other method of getting zero padding.
| 
|      2) Flexibility.  Using the precision to specify the zero padding
| 	allows the field width to be used for its normal function even
| 	when zero padding is desired.
+---------------

One other reason as well:  it's not possible to get zero padding when using
variable width fields (%*d) under the old scheme.  With the new scheme, use
%.*d for zero padding and %*.*d to choose zero padding or none at runtime.

++Brandon
-- 
Brandon S. Allbery, moderator of comp.sources.misc	     allbery@ncoast.org
uunet!hal.cwru.edu!ncoast!allbery		    ncoast!allbery@hal.cwru.edu
      Send comp.sources.misc submissions to comp-sources-misc@<backbone>
NCoast Public Access UN*X - (216) 781-6201, 300/1200/2400 baud, login: makeuser