mirror of
https://github.com/cc65/cc65.git
synced 2024-08-17 03:29:15 +00:00
316 lines
7.7 KiB
C
316 lines
7.7 KiB
C
/*
|
|
!!DESCRIPTION!! C-Manual Chapter 8.5: Structure and Union declarations
|
|
!!ORIGIN!! LCC 4.1 Testsuite
|
|
!!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC
|
|
*/
|
|
|
|
#include "common.h"
|
|
|
|
struct defs {
|
|
int cbits; /* No. of bits per char */
|
|
int ibits; /* int */
|
|
int sbits; /* short */
|
|
int lbits; /* long */
|
|
int ubits; /* unsigned */
|
|
int fbits; /* float */
|
|
int dbits; /* double */
|
|
#ifndef NO_FLOATS
|
|
float fprec; /* Smallest number that can be */
|
|
float dprec; /* significantly added to 1. */
|
|
#endif
|
|
int flgs; /* Print return codes, by section */
|
|
int flgm; /* Announce machine dependencies */
|
|
int flgd; /* give explicit diagnostics */
|
|
int flgl; /* Report local return codes. */
|
|
int rrc; /* recent return code */
|
|
int crc; /* Cumulative return code */
|
|
char rfs[8]; /* Return from section */
|
|
};
|
|
|
|
int lbits; /* long */
|
|
int ubits; /* unsigned */
|
|
int fbits; /* float */
|
|
int dbits; /* double */
|
|
#ifndef NO_FLOATS
|
|
float fprec; /* Smallest number that can be */
|
|
float dprec; /* significantly added to 1. */
|
|
#endif
|
|
int flgs; /* Print return codes, by section */
|
|
int flgm; /* Announce machine dependencies */
|
|
int flgd; /* give explicit diagnostics */
|
|
int flgl; /* Report local return codes. */
|
|
int rrc; /* recent return code */
|
|
int crc; /* Cumulative return code */
|
|
char rfs[8]; /* Return from section */
|
|
|
|
#ifndef NO_OLD_FUNC_DECL
|
|
s85(pd0) /* 8.5 Structure and union declarations */
|
|
struct defs *pd0;
|
|
{
|
|
#else
|
|
int s85(struct defs *pd0){
|
|
#endif
|
|
static char s85er[] = "s85,er%d\n";
|
|
static char qs85[8] = "s85 ";
|
|
int rc;
|
|
char *ps, *pt;
|
|
|
|
struct tnode {
|
|
char tword[20];
|
|
int count;
|
|
struct tnode *left;
|
|
struct tnode *right;
|
|
};
|
|
|
|
struct tnode s1, s2, *sp;
|
|
|
|
struct{
|
|
char cdummy;
|
|
char c;
|
|
} sc;
|
|
|
|
struct{
|
|
char cdummy;
|
|
short s;
|
|
} ss;
|
|
|
|
struct{
|
|
char cdummy;
|
|
int i;
|
|
} si;
|
|
|
|
struct{
|
|
char cdummy;
|
|
long l;
|
|
} sl;
|
|
|
|
struct{
|
|
char cdummy;
|
|
unsigned u;
|
|
} su;
|
|
|
|
struct{
|
|
char cdummy;
|
|
#ifndef NO_FLOATS
|
|
float f;
|
|
#else
|
|
signed f;
|
|
#endif
|
|
} sf;
|
|
|
|
struct{
|
|
char cdummy;
|
|
#ifndef NO_FLOATS
|
|
double d;
|
|
#else
|
|
signed d;
|
|
#endif
|
|
} sd;
|
|
|
|
int diff[7], j;
|
|
|
|
static char *type[] = {
|
|
"char",
|
|
"short",
|
|
"int",
|
|
"long",
|
|
"unsigned",
|
|
#ifdef NO_FLOATS
|
|
"signed",
|
|
"signed",
|
|
#else
|
|
"float",
|
|
"double"
|
|
#endif
|
|
};
|
|
|
|
static char aln[] = " alignment: ";
|
|
|
|
#ifndef NO_BITFIELDS
|
|
struct{
|
|
int twobit:2;
|
|
int :1;
|
|
int threebit:3;
|
|
int onebit:1;
|
|
} s3;
|
|
#else
|
|
struct{
|
|
unsigned char twobit;
|
|
unsigned char threebit;
|
|
unsigned char onebit;
|
|
} s3;
|
|
#endif
|
|
|
|
union{
|
|
char u1[30];
|
|
short u2[30];
|
|
int u3[30];
|
|
long u4[30];
|
|
unsigned u5[30];
|
|
#ifndef NO_FLOATS
|
|
float u6[30];
|
|
double u7[30];
|
|
#else
|
|
signed u6[30];
|
|
signed u7[30];
|
|
#endif
|
|
} u0;
|
|
|
|
ps = qs85;
|
|
pt = pd0->rfs;
|
|
rc = 0;
|
|
while (*pt++ = *ps++);
|
|
|
|
/* Within a structure, the objects declared have
|
|
addresses which increase as their declarations are
|
|
read left to right.
|
|
*/
|
|
|
|
if( (char *)&s1.count - &s1.tword[0] <= 0
|
|
||(char *)&s1.left - (char *)&s1.count <= 0
|
|
||(char *)&s1.right - (char *)&s1.left <= 0){
|
|
if(pd0->flgd != 0) printf(s85er,1);
|
|
rc = rc+1;
|
|
}
|
|
|
|
/* Each non-field member of a structure begins on an
|
|
addressing boundary appropriate to its type.
|
|
*/
|
|
|
|
diff[0] = &sc.c - &sc.cdummy;
|
|
diff[1] = (char *)&ss.s - &ss.cdummy;
|
|
diff[2] = (char *)&si.i - &si.cdummy;
|
|
diff[3] = (char *)&sl.l - &sl.cdummy;
|
|
diff[4] = (char *)&su.u - &su.cdummy;
|
|
diff[5] = (char *)&sf.f - &sf.cdummy;
|
|
diff[6] = (char *)&sd.d - &sd.cdummy;
|
|
|
|
if(pd0->flgm != 0)
|
|
for(j=0; j<7; j++)
|
|
printf("%s%s%d\n",type[j],aln,diff[j]);
|
|
|
|
/* Field specifications are highly implementation de-
|
|
pendent. About the only thing we can do here is to
|
|
check is that the compiler accepts the field constructs,
|
|
and that they seem to work, after a fashion, at
|
|
run time...
|
|
*/
|
|
|
|
s3.threebit = 7;
|
|
s3.twobit = s3.threebit;
|
|
s3.threebit = s3.twobit;
|
|
|
|
if(s3.threebit != 3){
|
|
if(s3.threebit == -1){
|
|
if(pd0->flgm != 0) printf("Sign extension in fields\n");
|
|
}
|
|
else{
|
|
#ifdef NO_BITFIELDS
|
|
if(pd0->flgd != 0) printf("NO_BITFIELDS\n");
|
|
#else
|
|
if(pd0->flgd != 0) printf(s85er,2);
|
|
rc = rc+2;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
s3.onebit = 1;
|
|
if(s3.onebit != 1){
|
|
if(pd0->flgm != 0)
|
|
printf("Be especially careful with 1-bit fields!\n");
|
|
}
|
|
|
|
/* A union may be thought of as a structure all of whose
|
|
members begin at offset 0 and whose size is sufficient
|
|
to contain any of its members.
|
|
*/
|
|
|
|
if( (char *)u0.u1 - (char *)&u0 != 0
|
|
||(char *)u0.u2 - (char *)&u0 != 0
|
|
||(char *)u0.u3 - (char *)&u0 != 0
|
|
||(char *)u0.u4 - (char *)&u0 != 0
|
|
||(char *)u0.u5 - (char *)&u0 != 0
|
|
||(char *)u0.u6 - (char *)&u0 != 0
|
|
||(char *)u0.u7 - (char *)&u0 != 0){
|
|
if(pd0->flgd != 0) printf(s85er,4);
|
|
rc = rc+4;
|
|
}
|
|
|
|
if( sizeof u0 < sizeof u0.u1
|
|
||sizeof u0 < sizeof u0.u2
|
|
||sizeof u0 < sizeof u0.u3
|
|
||sizeof u0 < sizeof u0.u4
|
|
||sizeof u0 < sizeof u0.u5
|
|
||sizeof u0 < sizeof u0.u6
|
|
||sizeof u0 < sizeof u0.u7){
|
|
if(pd0->flgd != 0) printf(s85er,8);
|
|
rc = rc+8;
|
|
}
|
|
|
|
/* Finally, we check that the pointers work. */
|
|
|
|
s1.right = &s2;
|
|
s2.tword[0] = 2;
|
|
s1.right->tword[0] += 1;
|
|
if(s2.tword[0] != 3){
|
|
if(pd0->flgd != 0) printf(s85er,16);
|
|
rc = rc+16;
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
#ifdef NO_LOCAL_PROTOTYPES
|
|
int one();
|
|
#endif
|
|
|
|
/*********************************************************************************************
|
|
the main loop that launches the sections
|
|
*********************************************************************************************/
|
|
|
|
#ifndef NO_TYPELESS_STRUCT_PTR
|
|
int section(int j,struct* pd0){
|
|
#else
|
|
int section(int j,void* pd0){
|
|
#endif
|
|
switch(j){
|
|
case 0: return s85(pd0);
|
|
}
|
|
}
|
|
|
|
#define cq_sections 1
|
|
|
|
/*
|
|
C REFERENCE MANUAL (main)
|
|
*/
|
|
|
|
#ifndef NO_OLD_FUNC_DECL
|
|
main(n,args)
|
|
int n;
|
|
char **args;
|
|
{
|
|
#else
|
|
int main(int n,char **args) {
|
|
#endif
|
|
|
|
int j;
|
|
static struct defs d0, *pd0;
|
|
|
|
d0.flgs = 1; /* These flags dictate */
|
|
d0.flgm = 1; /* the verbosity of */
|
|
d0.flgd = 1; /* the program. */
|
|
d0.flgl = 1;
|
|
|
|
pd0 = &d0;
|
|
|
|
for (j=0; j<cq_sections; j++) {
|
|
d0.rrc=section(j,pd0);
|
|
d0.crc=d0.crc+d0.rrc;
|
|
if(d0.flgs != 0) printf("Section %s returned %d.\n",d0.rfs,d0.rrc);
|
|
}
|
|
|
|
if(d0.crc == 0) printf("\nNo errors detected.\n");
|
|
else printf("\nFailed.\n");
|
|
|
|
return d0.crc;
|
|
}
|