Re: C Unions

From: Jerry Avins <jya_at_ieee.org>
Date: Tue, 07 Nov 2000 11:14:11 -0500

Maybe another example will help. The program 'ticks' turns off the
periodic clock interrupt on a DOS machine. (Windows locks up without
it.) I needed it to get rid of jitter in the output of a signal
generator, and there was no Forth handy. Turning off the clock stops the
system clock; in order to update it when interrupts are restored,
BIOS calls need to be made. these calls include pointers to structures
that include various elements of time and date. REGS is a union type
that allows one piece of the code to read a register either as the
16-bit value in A or the 8-bit values in AH and AL. Without that dual
interpretation of the data, useless data diddling would be needed. With
it, I can do the equivalent of TIME 2@ HOUR ! MINUTE ! .

Does that help?

Jerry

P.S. The attached code works; all are welcome to use it. An
acknowledgment will be appreciated if you do.

--
Engineering is the art of making what you want from things you can get.
-----------------------------------------------------------------------
Elizabeth D Rather wrote:
>
> Ok, why would you do this?
>
> Thanks,
> Elizabeth  (another C illiterate)
>
> At 06:53 PM 10/30/2000 -0500, you wrote:
> >Hi Mike:
> >
> >You wrote:
> > >
> > > Could anyone explain to a C illiterate how to interpret a C class union?
> > >
> >
> >A union in C gives the bytes in question "multiple personalities". As
> >far as the compiler is concerned the names refer to the same bytes. if
> >you call
> >
> > > For example:
> > >
> > > -------------------------------------------------
> > > typedef struct _PROPSHEETPAGE {
> > >     DWORD dwSize;
> > >     DWORD dwFlags;
> > >     HINSTANCE hInstance;
> > >     union {
> > >         LPCSTR pszTemplate;
> > >         LPCDLGTEMPLATE pResource;
> > >         };
> >
> >         Here you can refer to _PROPSHEETPAGE.pszTemplate or
> >_PROPSHEETPAGE.pResource and you will get the data at the same
> >address. If one of the types is larger than the other the larger
> >number of bytes would be allocated and of course the extra bytes would
> >be unused when storing a smaller type. But
> > >
> > > -------------------------------------------------
> > > CLASS PROPSHEETPAGE
> > >     VARIABLE dwSize
> > >     VARIABLE dwFlags
> > >     VARIABLE hInstance
> > >             \ union
> > >     VARIABLE pszTemplate
> > >     VARIABLE pResource
> >
> >this will not work correctly. You need only one variable for each of
> >the unions (provided the type is covered by four bytes.
> >
> >And noe the ubiquitous HTH :)
> >
> >--
> >John McKeon
> >jmck_at_customsightsound.com
> >
> >_______________________________________________
> >Sftalk mailing list Sftalk_at_forth.com
> >Visit Sftalk on the web at http://www.forthinc.com/mailman/listinfo/sftalk
>
> ================================================
> Elizabeth D. Rather   (US & Canada) 800-55-FORTH
> FORTH Inc.                       +1 310-372-8493
> 111 N. Sepulveda Blvd. #300 Fax: +1 310-318-7130
> Manhattan Beach, CA 90266
> http://www.forth.com
>
> "Forth-based products and Services for real-time
> applications since 1973."
> ================================================
>
> _______________________________________________
> Sftalk mailing list Sftalk_at_forth.com
> Visit Sftalk on the web at http://www.forthinc.com/mailman/listinfo/sftalk

/* This program controls the clock-tick interrupt. I needed it
    to do some loop timing without interference from the interrupt.
    It returns zero if it leaves the interrupt enabled, 1 if it leaves
    it disabled, 2 if the CMOS clock can't be read but the interrupt
    is enabled, and 3 if the first command line argument isn't "on" or
    "off". If it can, it copies (CMOS clock) --> (BIOS clock) when it
    enables the clock interrupt (INT 0). This version doesn't check
    to see if it succeeds with the interrupts: it assumes that the
    interrupt controller is where it ought to be, and that it works.
        Unfortunately, the BIOS settime() routine also sets the CMOS
    clock and disturbs it. If now.ti_hund is zero, the call often sets
    the clock back a second.
                                                J. Y. Avins: 11/90
    Changed outport to outportb etc. 2/1/95
*/

#include <stdio.h>
#include <dos.h>
#define CLOCK 0x1A /* ROM BIOS clock call */

#define BCDtoHEX(b) ((b)-6*((b)>>4)) /* Packed BCD byte to char */

int GetRealTime(void);
union REGS d_regs;
union REGS t_regs;
union REGS d_chek;
void settime(struct time *timep); /* da_year is int . */
void setdate(struct date *datep); /* The other elements */
struct date today; /* of these structures */
struct time now; /* are char . */

int GetRealTime() /* BCD time from CMOS clock -> DOS structures */

{
do
    {
    d_regs.h.ah = d_chek.h.ah = 4 ; /* BIOS call function for date. */
    t_regs.h.ah = 2 ; /* BIOS call function for time. */
    int86(CLOCK, &d_regs, &d_regs);
    int86(CLOCK, &t_regs, &t_regs);
    int86(CLOCK, &d_chek, &d_chek);
    if( t_regs.x.cflag ) return(1); /* Carry set if error. */
    }
while (d_regs.h.dl != d_chek.h.dl); /* No bugs at midnight. */

today.da_year = 100 * BCDtoHEX(d_regs.h.ch) /* century */
                    + BCDtoHEX(d_regs.h.cl); /* year */
today.da_mon = BCDtoHEX(d_regs.h.dh); /* month */
today.da_day = BCDtoHEX(d_regs.h.dl);
now.ti_hour = BCDtoHEX(t_regs.h.ch);
now.ti_min = BCDtoHEX(t_regs.h.cl);
now.ti_sec = BCDtoHEX(t_regs.h.dh);
now.ti_hund = 50;
return(0);
}

int main(int argc, char *argv[])
{
if( ! stricmp(argv[1], "off") )
    {
    outportb(33, inportb(33)|1); /* Bit 0 of port 33 disables INT 0. */
    exit(1);
    }

if( ! stricmp(argv[1], "on") )
    {
    outportb(33, inportb(33)&~1);
    if( GetRealTime() )
        {
        puts("Cannot read the CMOS clock.");
        exit(2);
        }

    settime(&now);
    setdate(&today);
    if ( (argc > 1) && stricmp(argv[2], "-s") )
        printf("System clock set to %02d/%02d/%d; %2d:%02d:%02d\n",
                today.da_mon, today.da_day, today.da_year,
                now.ti_hour, now.ti_min, now.ti_sec);
    exit(0);
    }

puts("TICKS turns INT 0 (system clock ticks) on and off. When it");
puts("enables INT 0, it sets the system clock to match the AT CMOS clock.");
puts("The -s switch suppresses the update report when INT 0 is enabled.");
puts("If a CMOS clock is absent, the system clock will be undisturbed.\n");
puts("usage: \x1b[1mclock on [-s]\x1b[0m or \x1b[1mclock off\x1b[0m\n");
exit(3);
}
Received on Tue Nov 07 2000 - 08:26:30 PST


Subscribe to our e-mail list service. It's free for all SwiftForth and SwiftX users!

This archive was generated 06-Feb-2012. Archive updated nightly.