[comp.lang.c] compiler predefines

dhesi@bsu-cs.UUCP (Rahul Dhesi) (07/22/87)

#if 0    /* skip junk when compiling attached C program */
(I added comp.lang.c to the newsgroups and am directing followups there.)

In article <8888@tekecs.TEK.COM> snoopy@doghouse.gwd.tek.com (Snoopy) 
writes:
>In article <23741@sun.uucp> guy%gorodish@Sun.COM (Guy Harris) writes:
>>  There *should* either be a predicate built into the C
>> preprocessor/compiler or a #define constant in some system include
>> file;
>YES! YES!  Anyone for "LITTLE_ENDIAN" and "BIG_ENDIAN" ?  And all the
>predefines should be documented.
[...]
>But back to the main point, #ifdefs should reflect what you're
>REALLY testing for.  Use #ifdef LITTLE_ENDIAN, or #ifdef MASSBUS,
>not #ifdef vax, or worse, some internal codename for a machine.

Yes, PLEASE do not use machine names except in ONE place, where you
select orthognoal attributes based on machine identity.  Use the
names of these attributes everywhere else.

I hope the problem of writing software that will adapt itself to
byte/word/int/long/short size and endianism and 1's vs 2's complement
will be solved by the following program.  The program can be compiled
and executed from a makefile, and generates a series of defines that
may then be included and tested by the remaining source files.

Sample output when executed on a VAX-11/785 under 4.3BSD (I manually
added the comments):

#define Mch_Csz 8       /* size of char */
#define Mch_Ssz 16      /* size of short */
#define Mch_Isz 32      /* size of int */
#define Mch_Lsz 32      /* size of long */
#define Mch_LE 1        /* little-endian */
#define Mch_sgc 1       /* char may be signed */

John Cowan, the author, is somewhat unclear about the copyright status
of this program.  I suspect he really wanted it to be public domain,
but wanted appropriate credit for it, so added the copyright notice.
#endif /* skip junk */

/* The contents of the following program are copyright 1987 by John Cowan.
It is hereby released to the public domain.

This program emits C #define statements to the standard output describing
the machine it is executing on.  The following #defines are generated:
        Mch_Csz -       size of a char, in bits
        Mch_Ssz -       size of a short int, in bits
        Mch_Isz -       size of a plain int, in bits
        Mch_Lsz -       size of a long int, in bits
        Mch_BE -        defined if the machine is big-endian; that is, if
                        the most significant byte in a number appears first.
        Mch_LE -        defined if the machine is little-endian; that is, if
                        the least significant byte in a number appears first.
        Mch_PDP -       defined if the machine uses PDP-11 byte ordering;
                        LE for bytes-in-a-word and BE for words-in-a-long.
        Mch_ONE -       defined if the machine uses one's complement arithmetic.
        Mch_sgc -       defined if characters can be signed.
*/

#include <stdio.h>

char bittest[6] = "\001\001\001\001\001";
char endtest[6] = "\001\002\003\004\005";
long be = 1;
long le = 1;
long pdp;
int byteoff;
int bytesize;
long longval;

main()
        {
        int i;

        byteoff = (*(int *) bittest & 2047) - 1;
        switch (byteoff) {
        case 256: bytesize = 8; break;
        case 512: bytesize = 9; break;
        case 1024: bytesize = 10; break;
        default: fprintf(stderr, "mch: bogus byte size\n"); exit(1);
                }
        printf("#define Mch_Csz %d\n", bytesize);
        printf("#define Mch_Ssz %d\n", sizeof(short) * bytesize);
        printf("#define Mch_Isz %d\n", sizeof(int) * bytesize);
        printf("#define Mch_Lsz %d\n", sizeof(long) * bytesize);
        longval = *(long *) endtest;
        for (i = 0; i < sizeof(long); i++) {
                be *= byteoff;
                be += endtest[i];
                }
        for (i = sizeof(long) - 1; i >= 0; i--) {
                le *= byteoff;
                le += endtest[i];
                }
        pdp = 0x02010403;
        if (longval == be)
                printf("#define Mch_BE 1\n");
        else if (longval == le)
                printf("#define Mch_LE 1\n");
        else if (longval == pdp)
                printf("#define Mch_PDP 1\n");
        else {
                fprintf(stderr, "mch: bogus endianism\n");
                exit(1);
                }
        if (~0 == 0)
                printf("#define Mch_ONE 1\n");
        if ('\377' < 0)       /* modified 1987/07/22 R. Dhesi */
                printf("#define Mch_sgc 1\n");
        }
/*
-- 
Rahul Dhesi         UUCP:  {ihnp4,seismo}!{iuvax,pur-ee}!bsu-cs!dhesi
*/

abh@pogo.cray.com (Andy Hastings) (07/27/87)

In article <865@bsu-cs.UUCP>, dhesi@bsu-cs.UUCP (Rahul Dhesi) writes:
> This program emits C #define statements to the standard output describing
> the machine it is executing on.  The following #defines are generated:
>         Mch_Csz -       size of a char, in bits
>         Mch_Ssz -       size of a short int, in bits
>         Mch_Isz -       size of a plain int, in bits
>         Mch_Lsz -       size of a long int, in bits
>         Mch_BE -        defined if the machine is big-endian; that is, if
>                         the most significant byte in a number appears first.
>         Mch_LE -        defined if the machine is little-endian; that is, if
>                         the least significant byte in a number appears first.
>         Mch_PDP -       defined if the machine uses PDP-11 byte ordering;
>                         LE for bytes-in-a-word and BE for words-in-a-long.
>         Mch_ONE -       defined if the machine uses one's complement arithmetic.
>         Mch_sgc -       defined if characters can be signed.

	Hmm.  The program said `mch: bogus byte size' when I ran it on my
CRAY X-MP.  I changed the definition of bittest to:
		char bittest[9] = "\001\001\001\001\001\001\001\001";
and then I got the correct results:
		#define Mch_Csz 8
		#define Mch_Ssz 64
		#define Mch_Isz 64
		#define Mch_Lsz 64
		#define Mch_BE 1
Much better.

-Andy Hastings			ihnp4!cray!hall!abh
 Cray Research, Inc.		sun!tundra!hall!abh

*CRAY X-MP is a trademark of Cray Research, Inc.