struct-layout-encoding-1_generate.c [plain text]
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
#include "generate-random.h"
#if LLONG_MAX != 9223372036854775807LL && __LONG_LONG_MAX__ != 9223372036854775807LL
# error Need 64-bit long long
#endif
typedef unsigned int hashval_t;
enum TYPE
{
TYPE_INT,
TYPE_UINT,
TYPE_CINT,
TYPE_CUINT,
TYPE_FLOAT,
TYPE_CFLOAT,
TYPE_SENUM,
TYPE_UENUM,
TYPE_PTR,
TYPE_FNPTR,
TYPE_OTHER
};
struct types
{
const char *name;
enum TYPE type;
unsigned long long int maxval;
char bitfld;
};
struct types base_types[] = {
{ "char", TYPE_UINT, 127, 'C' },
{ "signed char", TYPE_INT, 127, 'C' },
{ "unsigned char", TYPE_UINT, 255, 'C' },
{ "short int", TYPE_INT, 32767, 'S' },
{ "unsigned short int", TYPE_UINT, 65535, 'S' },
{ "int", TYPE_INT, 2147483647, 'I' },
{ "unsigned int", TYPE_UINT, 4294967295U, 'I' },
{ "long int", TYPE_INT, 9223372036854775807LL, 'L' },
{ "unsigned long int", TYPE_UINT, 18446744073709551615ULL, 'L' },
{ "long long int", TYPE_INT, 9223372036854775807LL, 'Q' },
{ "unsigned long long int", TYPE_UINT, 18446744073709551615ULL, 'Q' },
{ "bool", TYPE_UINT, 1, 'B' },
{ "void *", TYPE_PTR, 0, 0 },
{ "char *", TYPE_PTR, 0, 0 },
{ "int *", TYPE_PTR, 0, 0 },
{ "float", TYPE_FLOAT, 0, 0 },
{ "double", TYPE_FLOAT, 0, 0 },
#define NTYPES1 16
#if 0
{ "enum E0", TYPE_UENUM, 0, ' ' },
{ "enum E1", TYPE_UENUM, 1, ' ' },
{ "enum E2", TYPE_SENUM, 3, ' ' },
{ "enum E3", TYPE_SENUM, 127, ' ' },
{ "enum E4", TYPE_UENUM, 255, ' ' },
{ "enum E5", TYPE_SENUM, 32767, ' ' },
{ "enum E6", TYPE_UENUM, 65535, ' ' },
{ "enum E7", TYPE_SENUM, 2147483647, ' ' },
{ "enum E8", TYPE_UENUM, 4294967295U, ' ' },
{ "enum E9", TYPE_SENUM, 1099511627775LL, ' ' },
#endif
#define NTYPES2 (sizeof (base_types) / sizeof (base_types[0]))
};
struct types complex_types[] = {
{ "_Complex char", TYPE_CUINT, 127, 0 },
{ "_Complex signed char", TYPE_CINT, 127, 0 },
{ "_Complex unsigned char", TYPE_CUINT, 255, 0 },
{ "_Complex short int", TYPE_CINT, 32767, 0 },
{ "_Complex unsigned short int", TYPE_CUINT, 65535, 0 },
{ "_Complex int", TYPE_CINT, 2147483647, 0 },
{ "_Complex unsigned int", TYPE_CUINT, 4294967295U, 0 },
{ "_Complex long int", TYPE_CINT, 9223372036854775807LL, 0 },
{ "_Complex unsigned long int", TYPE_CUINT, 18446744073709551615ULL, 0 },
{ "_Complex long long int", TYPE_CINT, 9223372036854775807LL, 0 },
{ "_Complex unsigned long long int", TYPE_CUINT, 18446744073709551615ULL, 0 },
{ "_Complex float", TYPE_CFLOAT, 0, 0 },
{ "_Complex double", TYPE_CFLOAT, 0, 0 },
#define NCTYPES2 (sizeof (complex_types) / sizeof (complex_types[0]))
};
struct types vector_types[] = {
{ "v8qi", TYPE_OTHER, 0, 0 },
{ "v16qi", TYPE_OTHER, 0, 0 },
{ "v2hi", TYPE_OTHER, 0, 0 },
{ "v4hi", TYPE_OTHER, 0, 0 },
{ "v8hi", TYPE_OTHER, 0, 0 },
{ "v2si", TYPE_OTHER, 0, 0 },
{ "v4si", TYPE_OTHER, 0, 0 },
{ "v1di", TYPE_OTHER, 0, 0 },
{ "v2di", TYPE_OTHER, 0, 0 },
{ "v2sf", TYPE_OTHER, 0, 0 },
{ "v4sf", TYPE_OTHER, 0, 0 },
{ "v16sf", TYPE_OTHER, 0, 0 },
{ "v2df", TYPE_OTHER, 0, 0 },
{ "u8qi", TYPE_OTHER, 0, 0 },
{ "u16qi", TYPE_OTHER, 0, 0 },
{ "u2hi", TYPE_OTHER, 0, 0 },
{ "u4hi", TYPE_OTHER, 0, 0 },
{ "u8hi", TYPE_OTHER, 0, 0 },
{ "u2si", TYPE_OTHER, 0, 0 },
{ "u4si", TYPE_OTHER, 0, 0 },
{ "u1di", TYPE_OTHER, 0, 0 },
{ "u2di", TYPE_OTHER, 0, 0 },
{ "u2sf", TYPE_OTHER, 0, 0 },
{ "u4sf", TYPE_OTHER, 0, 0 },
{ "u16sf", TYPE_OTHER, 0, 0 },
{ "u2df", TYPE_OTHER, 0, 0 },
{ "__m64", TYPE_OTHER, 0, 0 },
{ "__m128", TYPE_OTHER, 0, 0 }
#define NVTYPES2 (sizeof (vector_types) / sizeof (vector_types[0]))
};
struct types bitfld_types[NTYPES2];
int n_bitfld_types;
enum ETYPE
{
ETYPE_TYPE,
ETYPE_ARRAY,
ETYPE_BITFLD,
ETYPE_STRUCT,
ETYPE_UNION,
ETYPE_STRUCT_ARRAY,
ETYPE_UNION_ARRAY
};
struct entry
{
#ifdef __GNUC__
enum ETYPE etype : 8;
#else
unsigned char etype;
#endif
unsigned short len;
unsigned char arr_len;
struct types *type;
const char *attrib;
struct entry *next;
};
#define HASH_SIZE 32749
static struct entry *hash_table[HASH_SIZE];
static int idx, limidx, output_one;
static const char *destdir;
static const char *srcdir;
FILE *outfile;
void
switchfiles (int fields)
{
static int filecnt;
static char *destbuf, *destptr;
++filecnt;
if (outfile)
fclose (outfile);
if (output_one)
{
outfile = stdout;
return;
}
if (destbuf == NULL)
{
size_t len = strlen (destdir);
destbuf = malloc (len + 20);
if (!destbuf)
abort ();
memcpy (destbuf, destdir, len);
if (!len || destbuf[len - 1] != '/')
destbuf[len++] = '/';
destptr = destbuf + len;
}
sprintf (destptr, "t%03d_main.m", filecnt);
outfile = fopen (destbuf, "w");
if (outfile == NULL)
{
fail:
fputs ("failed to create test files\n", stderr);
exit (1);
}
if (filecnt == 2
|| filecnt == 3
|| filecnt == 4
|| filecnt == 6
|| filecnt == 7
|| filecnt == 8
|| filecnt == 11
|| filecnt == 12
|| filecnt == 15
|| filecnt == 22)
{
fprintf (outfile, "\
/* { dg-do run { xfail powerpc*-*-darwin* powerpc*-*-aix* } } */\n\
/* { dg-options \"-w -I%s -fgnu-runtime\" } */\n", srcdir);
}
else if (filecnt >= 25)
{
fprintf (outfile, "\
/* { dg-do run { xfail *-*-* } } */\n\
/* { dg-options \"-w -I%s -fgnu-runtime\" } */\n", srcdir);
}
else
{
fprintf (outfile, "\
/* { dg-do run } */\n\
/* { dg-options \"-w -I%s -fgnu-runtime\" } */\n", srcdir);
}
fprintf(outfile, "#include <objc/encoding.h> \n\
#include \"struct-layout-1.h\"\n\
\n\
int fails; \n\
#define TX(n, type, attrs, fields, ops) \\\n\
type S##n { fields } attrs; \\\n\
void test##n (void) \\\n\
{ \\\n\
char *encoding = @encode (type S##n); \\\n\
if (objc_sizeof_type (encoding) != sizeof(type S##n)) \\\n\
{ \\\n\
fails ++; \\\n\
printf(#type \" { \" #fields \"} size is %%u, but is calulated as %%u\\n\", \\\n\
sizeof(type S##n), objc_sizeof_type (encoding)); \\\n\
} \\\n\
if (objc_alignof_type (encoding) != __alignof__ (type S##n)) \\\n\
{ \\\n\
fails ++; \\\n\
printf(#type \" { \" #fields \"} align is %%u, but is calulated as %%u\\n\", \\\n\
__alignof__ (type S##n), objc_alignof_type (encoding)); \\\n\
} \\\n\
}\n\
#include \"t%03d_test.h\"\n\
#undef TX\n\
\n\
int main (void)\n\
{\n\
#define TX(n, type, attrs, fields, ops) test##n ();\n\
#include \"t%03d_test.h\"\n\
#undef TX\n\
if (fails)\n\
{\n\
fflush (stdout);\n\
abort ();\n\
}\n\
exit (0);\n\
}\n", filecnt, filecnt);
fclose (outfile);
sprintf (destptr, "t%03d_test.h", filecnt);
outfile = fopen (destbuf, "w");
if (outfile == NULL)
goto fail;
if (fields <= 2)
limidx = idx + 300;
else if (fields <= 4)
limidx = idx + 200;
else if (fields <= 6)
limidx = idx + 100;
else
limidx = idx + 50;
}
unsigned long long int
getrandll (void)
{
unsigned long long int ret;
ret = generate_random () & 0xffffff;
ret |= (generate_random () & 0xffffffLL) << 24;
ret |= ((unsigned long long int) generate_random ()) << 48;
return ret;
}
int
subfield (struct entry *e, char *letter)
{
int i, type;
char buf[20];
const char *p;
switch (e[0].etype)
{
case ETYPE_STRUCT:
case ETYPE_UNION:
case ETYPE_STRUCT_ARRAY:
case ETYPE_UNION_ARRAY:
type = e[0].attrib ? 1 + (generate_random () & 3) : 0;
if (e[0].etype == ETYPE_STRUCT || e[0].etype == ETYPE_STRUCT_ARRAY)
p = "struct";
else
p = "union";
if (e[0].etype == ETYPE_STRUCT_ARRAY || e[0].etype == ETYPE_UNION_ARRAY)
{
if (e[0].arr_len == 255)
snprintf (buf, 20, "%c[]", *letter);
else
snprintf (buf, 20, "%c[%d]", *letter, e[0].arr_len);
}
else
{
buf[0] = *letter;
buf[1] = '\0';
}
++*letter;
switch (type)
{
case 0:
case 3:
case 4:
fprintf (outfile, "%s{", p);
break;
case 1:
fprintf (outfile, "%s %s{", e[0].attrib, p);
break;
case 2:
fprintf (outfile, "%s %s{", p, e[0].attrib);
break;
}
for (i = 1; i <= e[0].len; )
i += subfield (e + i, letter);
switch (type)
{
case 0:
case 1:
case 2:
fprintf (outfile, "}%s;", buf);
break;
case 3:
fprintf (outfile, "}%s %s;", e[0].attrib, buf);
break;
case 4:
fprintf (outfile, "}%s %s;", buf, e[0].attrib);
break;
}
return 1 + e[0].len;
case ETYPE_TYPE:
case ETYPE_ARRAY:
if (e[0].etype == ETYPE_ARRAY)
{
if (e[0].arr_len == 255)
snprintf (buf, 20, "%c[]", *letter);
else
snprintf (buf, 20, "%c[%d]", *letter, e[0].arr_len);
}
else
{
buf[0] = *letter;
buf[1] = '\0';
}
++*letter;
if (e[0].attrib)
switch (generate_random () % 3)
{
case 0:
fprintf (outfile, "%s %s %s;", e[0].attrib, e[0].type->name, buf);
break;
case 1:
fprintf (outfile, "%s %s %s;", e[0].type->name, e[0].attrib, buf);
break;
case 2:
fprintf (outfile, "%s %s %s;", e[0].type->name, buf, e[0].attrib);
break;
}
else
fprintf (outfile, "%s %s;", e[0].type->name, buf);
return 1;
case ETYPE_BITFLD:
if (e[0].len == 0)
{
if (e[0].attrib)
switch (generate_random () % 3)
{
case 0:
fprintf (outfile, "%s %s:0;", e[0].attrib, e[0].type->name);
break;
case 1:
fprintf (outfile, "%s %s:0;", e[0].type->name, e[0].attrib);
break;
case 2:
fprintf (outfile, "%s:0 %s;", e[0].type->name, e[0].attrib);
break;
}
else
fprintf (outfile, "%s:0;", e[0].type->name);
++*letter;
return 1;
}
switch (e[0].type->bitfld)
{
case 'C':
case 'S':
case 'I':
case 'L':
case 'Q':
snprintf (buf, 20, "B%cN(%d)", e[0].type->bitfld, e[0].len);
break;
case 'B':
case ' ':
snprintf (buf, 20, "%d", e[0].len);
break;
default:
abort ();
}
if (e[0].attrib)
switch (generate_random () % 3)
{
case 0:
fprintf (outfile, "%s %s %c:%s;", e[0].attrib, e[0].type->name,
*letter, buf);
break;
case 1:
fprintf (outfile, "%s %s %c:%s;", e[0].type->name, e[0].attrib,
*letter, buf);
break;
case 2:
fprintf (outfile, "%s %c:%s %s;", e[0].type->name, *letter,
buf, e[0].attrib);
break;
}
else
fprintf (outfile, "%s %c:%s;", e[0].type->name, *letter, buf);
++*letter;
return 1;
default:
abort ();
}
}
char namebuf[1024];
void
output_FNB (char mode, struct entry *e)
{
unsigned long long int l1, l2, m;
int signs = 0;
const char *p, *q;
if (e->type->type == TYPE_OTHER)
{
if (mode == 'B')
abort ();
fprintf (outfile, "N(%d,%s)", idx, namebuf);
return;
}
fprintf (outfile, "%c(%d,%s,", mode, idx, namebuf);
l1 = getrandll ();
l2 = getrandll ();
switch (e->type->type)
{
case TYPE_INT:
signs = generate_random () & 3;
m = e->type->maxval;
if (mode == 'B')
m &= e->len > 1 ? (1ULL << (e->len - 1)) - 1 : 1;
l1 &= m;
l2 &= m;
fprintf (outfile, "%s%llu%s,%s%llu%s",
(signs & 1) ? "-" : "", l1, l1 > 2147483647 ? "LL" : "",
(signs & 2) ? "-" : "", l2, l2 > 2147483647 ? "LL" : "");
break;
case TYPE_UINT:
m = e->type->maxval;
if (mode == 'B')
m &= (1ULL << e->len) - 1;
l1 &= m;
l2 &= m;
fprintf (outfile, "%lluU%s,%lluU%s", l1, l1 > 4294967295U ? "LL" : "",
l2, l2 > 4294967295U ? "LL" : "");
break;
case TYPE_FLOAT:
l1 &= 0xffffff;
l2 &= 0xffffff;
signs = generate_random () & 3;
fprintf (outfile, "%s%f,%s%f", (signs & 1) ? "-" : "",
((double) l1) / 64, (signs & 2) ? "-" : "", ((double) l2) / 64);
break;
case TYPE_CINT:
signs = generate_random () & 3;
l1 &= e->type->maxval;
l2 &= e->type->maxval;
fprintf (outfile, "CINT(%s%llu%s,%s%llu%s),",
(signs & 1) ? "-" : "", l1, l1 > 2147483647 ? "LL" : "",
(signs & 2) ? "-" : "", l2, l2 > 2147483647 ? "LL" : "");
signs = generate_random () & 3;
l1 = getrandll ();
l2 = getrandll ();
l1 &= e->type->maxval;
l2 &= e->type->maxval;
fprintf (outfile, "CINT(%s%llu%s,%s%llu%s)",
(signs & 1) ? "-" : "", l1, l1 > 2147483647 ? "LL" : "",
(signs & 2) ? "-" : "", l2, l2 > 2147483647 ? "LL" : "");
break;
case TYPE_CUINT:
l1 &= e->type->maxval;
l2 &= e->type->maxval;
fprintf (outfile, "CINT(%lluU%s,%lluU%s),",
l1, l1 > 4294967295U ? "LL" : "",
l2, l2 > 4294967295U ? "LL" : "");
l1 = getrandll ();
l2 = getrandll ();
l1 &= e->type->maxval;
l2 &= e->type->maxval;
fprintf (outfile, "CINT(%lluU%s,%lluU%s)",
l1, l1 > 4294967295U ? "LL" : "",
l2, l2 > 4294967295U ? "LL" : "");
break;
case TYPE_CFLOAT:
l1 &= 0xffffff;
l2 &= 0xffffff;
signs = generate_random () & 3;
fprintf (outfile, "CDBL(%s%f,%s%f),",
(signs & 1) ? "-" : "", ((double) l1) / 64,
(signs & 2) ? "-" : "", ((double) l2) / 64);
l1 = getrandll ();
l2 = getrandll ();
l1 &= 0xffffff;
l2 &= 0xffffff;
signs = generate_random () & 3;
fprintf (outfile, "CDBL(%s%f,%s%f)",
(signs & 1) ? "-" : "", ((double) l1) / 64,
(signs & 2) ? "-" : "", ((double) l2) / 64);
break;
case TYPE_UENUM:
if (e->type->maxval == 0)
fputs ("e0_0,e0_0", outfile);
else if (e->type->maxval == 1)
fprintf (outfile, "e1_%lld,e1_%lld", l1 & 1, l2 & 1);
else
{
p = strchr (e->type->name, '\0');
while (--p >= e->type->name && *p >= '0' && *p <= '9');
p++;
l1 %= 7;
l2 %= 7;
if (l1 > 3)
l1 += e->type->maxval - 6;
if (l2 > 3)
l2 += e->type->maxval - 6;
fprintf (outfile, "e%s_%lld,e%s_%lld", p, l1, p, l2);
}
break;
case TYPE_SENUM:
p = strchr (e->type->name, '\0');
while (--p >= e->type->name && *p >= '0' && *p <= '9');
p++;
l1 %= 7;
l2 %= 7;
fprintf (outfile, "e%s_%s%lld,e%s_%s%lld",
p, l1 < 3 ? "m" : "",
l1 == 3 ? 0LL : e->type->maxval - (l1 & 3),
p, l2 < 3 ? "m" : "",
l2 == 3 ? 0LL : e->type->maxval - (l2 & 3));
break;
case TYPE_PTR:
l1 %= 256;
l2 %= 256;
fprintf (outfile, "(%s)&intarray[%lld],(%s)&intarray[%lld]",
e->type->name, l1, e->type->name, l2);
break;
case TYPE_FNPTR:
l1 %= 10;
l2 %= 10;
fprintf (outfile, "fn%lld,fn%lld", l1, l2);
break;
default:
abort ();
}
fputs (")", outfile);
}
int
subvalues (struct entry *e, char *p, char *letter)
{
int i, j;
char *q;
if (p >= namebuf + sizeof (namebuf) - 32)
abort ();
p[0] = *letter;
p[1] = '\0';
q = p + 1;
switch (e[0].etype)
{
case ETYPE_STRUCT_ARRAY:
case ETYPE_UNION_ARRAY:
if (e[0].arr_len == 0 || e[0].arr_len == 255)
{
*letter += 1 + e[0].len;
return 1 + e[0].len;
}
i = generate_random () % e[0].arr_len;
snprintf (p, sizeof (namebuf) - (p - namebuf) - 1,
"%c[%d]", *letter, i);
q = strchr (p, '\0');
case ETYPE_STRUCT:
case ETYPE_UNION:
*q++ = '.';
++*letter;
for (i = 1; i <= e[0].len; )
{
i += subvalues (e + i, q, letter);
if (e[0].etype == ETYPE_UNION || e[0].etype == ETYPE_UNION_ARRAY)
{
*letter += e[0].len - i + 1;
break;
}
}
return 1 + e[0].len;
case ETYPE_TYPE:
++*letter;
output_FNB ('F', e);
return 1;
case ETYPE_ARRAY:
if (e[0].arr_len == 0 || e[0].arr_len == 255)
{
++*letter;
return 1;
}
i = generate_random () % e[0].arr_len;
snprintf (p, sizeof (namebuf) - (p - namebuf),
"%c[%d]", *letter, i);
output_FNB ('F', e);
if ((generate_random () & 7) == 0)
{
j = generate_random () % e[0].arr_len;
if (i != j)
{
snprintf (p, sizeof (namebuf) - (p - namebuf),
"%c[%d]", *letter, j);
output_FNB ('F', e);
}
}
++*letter;
return 1;
case ETYPE_BITFLD:
++*letter;
if (e[0].len != 0)
output_FNB ('B', e);
return 1;
}
}
#define mix(a,b,c) \
{ \
a -= b; a -= c; a ^= (c>>13); \
b -= c; b -= a; b ^= (a<< 8); \
c -= a; c -= b; c ^= ((b&0xffffffff)>>13); \
a -= b; a -= c; a ^= ((c&0xffffffff)>>12); \
b -= c; b -= a; b = (b ^ (a<<16)) & 0xffffffff; \
c -= a; c -= b; c = (c ^ (b>> 5)) & 0xffffffff; \
a -= b; a -= c; a = (a ^ (c>> 3)) & 0xffffffff; \
b -= c; b -= a; b = (b ^ (a<<10)) & 0xffffffff; \
c -= a; c -= b; c = (c ^ (b>>15)) & 0xffffffff; \
}
static hashval_t
iterative_hash (const void *k_in ,
register size_t length ,
register hashval_t initval )
{
register const unsigned char *k = (const unsigned char *)k_in;
register hashval_t a,b,c,len;
len = length;
a = b = 0x9e3779b9;
c = initval;
while (len >= 12)
{
a += (k[0] +((hashval_t)k[1]<<8) +((hashval_t)k[2]<<16) +((hashval_t)k[3]<<24));
b += (k[4] +((hashval_t)k[5]<<8) +((hashval_t)k[6]<<16) +((hashval_t)k[7]<<24));
c += (k[8] +((hashval_t)k[9]<<8) +((hashval_t)k[10]<<16)+((hashval_t)k[11]<<24));
mix(a,b,c);
k += 12; len -= 12;
}
c += length;
switch(len)
{
case 11: c+=((hashval_t)k[10]<<24);
case 10: c+=((hashval_t)k[9]<<16);
case 9 : c+=((hashval_t)k[8]<<8);
case 8 : b+=((hashval_t)k[7]<<24);
case 7 : b+=((hashval_t)k[6]<<16);
case 6 : b+=((hashval_t)k[5]<<8);
case 5 : b+=k[4];
case 4 : a+=((hashval_t)k[3]<<24);
case 3 : a+=((hashval_t)k[2]<<16);
case 2 : a+=((hashval_t)k[1]<<8);
case 1 : a+=k[0];
}
mix(a,b,c);
return c;
}
hashval_t
e_hash (const void *a)
{
const struct entry *e = a;
hashval_t ret = 0;
int i;
if (e[0].etype != ETYPE_STRUCT && e[0].etype != ETYPE_UNION)
abort ();
for (i = 0; i <= e[0].len; ++i)
{
int attriblen;
ret = iterative_hash (&e[i], offsetof (struct entry, attrib), ret);
attriblen = e[i].attrib ? strlen (e[i].attrib) : -1;
ret = iterative_hash (&attriblen, sizeof (int), ret);
if (e[i].attrib)
ret = iterative_hash (e[i].attrib, attriblen, ret);
}
return ret;
}
int
e_eq (const void *a, const void *b)
{
const struct entry *ea = a, *eb = b;
int i;
if (ea[0].etype != ETYPE_STRUCT && ea[0].etype != ETYPE_UNION)
abort ();
if (ea[0].len != eb[0].len)
return 0;
for (i = 0; i <= ea[0].len; ++i)
{
if (ea[i].etype != eb[i].etype
|| ea[i].len != eb[i].len
|| ea[i].arr_len != eb[i].arr_len
|| ea[i].type != eb[i].type)
return 0;
if ((ea[i].attrib == NULL) ^ (eb[i].attrib == NULL))
return 0;
if (ea[i].attrib && strcmp (ea[i].attrib, eb[i].attrib) != 0)
return 0;
}
return 1;
}
static int
e_exists (const struct entry *e)
{
struct entry *h;
hashval_t hval;
hval = e_hash (e);
for (h = hash_table[hval % HASH_SIZE]; h; h = h->next)
if (e_eq (e, h))
return 1;
return 0;
}
static void
e_insert (struct entry *e)
{
hashval_t hval;
hval = e_hash (e);
e->next = hash_table[hval % HASH_SIZE];
hash_table[hval % HASH_SIZE] = e;
}
void
output (struct entry *e)
{
int i;
char c;
struct entry *n;
const char *skip_cint = "";
if (e[0].etype != ETYPE_STRUCT && e[0].etype != ETYPE_UNION)
abort ();
if (e_exists (e))
return;
n = (struct entry *) malloc ((e[0].len + 1) * sizeof (struct entry));
memcpy (n, e, (e[0].len + 1) * sizeof (struct entry));
e_insert (n);
if (idx == limidx)
switchfiles (e[0].len);
for (i = 1; i <= e[0].len; ++i)
if ((e[i].etype == ETYPE_TYPE || e[i].etype == ETYPE_ARRAY)
&& (e[i].type->type == TYPE_CINT || e[i].type->type == TYPE_CUINT))
break;
if (i <= e[0].len)
skip_cint = "CI";
if (e[0].attrib)
fprintf (outfile, (generate_random () & 1)
? "TX%s(%d,%s %s,," : "TX%s(%d,%s,%s,", skip_cint,
idx, e[0].etype == ETYPE_STRUCT ? "struct" : "union",
e[0].attrib);
else if (e[0].etype == ETYPE_STRUCT)
fprintf (outfile, "T%s(%d,", skip_cint, idx);
else
fprintf (outfile, "U%s(%d,", skip_cint, idx);
c = 'a';
for (i = 1; i <= e[0].len; )
i += subfield (e + i, &c);
fputs (",", outfile);
c = 'a';
for (i = 1; i <= e[0].len; )
{
i += subvalues (e + i, namebuf, &c);
if (e[0].etype == ETYPE_UNION)
break;
}
fputs (")\n", outfile);
if (output_one && idx == limidx)
exit (0);
++idx;
}
enum FEATURE
{
FEATURE_VECTOR = 1,
FEATURE_COMPLEX = 2,
FEATURE_ZEROARRAY = 8,
FEATURE_ZEROBITFLD = 16,
ALL_FEATURES = FEATURE_COMPLEX | FEATURE_VECTOR | FEATURE_ZEROARRAY
| FEATURE_ZEROBITFLD
};
void
singles (enum FEATURE features)
{
struct entry e[2];
int i;
memset (e, 0, sizeof (e));
e[0].etype = ETYPE_STRUCT;
output (e);
e[0].etype = ETYPE_UNION;
output (e);
e[0].len = 1;
e[0].attrib = NULL;
for (i = 0; i < NTYPES2; ++i)
{
e[0].etype = ETYPE_STRUCT;
e[1].etype = ETYPE_TYPE;
e[1].type = &base_types[i];
output (e);
e[0].etype = ETYPE_UNION;
output (e);
}
if (features & FEATURE_COMPLEX)
for (i = 0; i < NCTYPES2; ++i)
{
e[0].etype = ETYPE_STRUCT;
e[1].etype = ETYPE_TYPE;
e[1].type = &complex_types[i];
output (e);
e[0].etype = ETYPE_UNION;
output (e);
}
if (features & FEATURE_VECTOR)
for (i = 0; i < NVTYPES2; ++i)
{
e[0].etype = ETYPE_STRUCT;
e[1].etype = ETYPE_TYPE;
e[1].type = &vector_types[i];
output (e);
e[0].etype = ETYPE_UNION;
output (e);
}
}
void
choose_type (enum FEATURE features, struct entry *e, int r, int in_array)
{
int i;
i = NTYPES2 - NTYPES1;
if (features & FEATURE_COMPLEX)
i += NCTYPES2;
if (features & FEATURE_VECTOR)
i += NVTYPES2;
r >>= 2;
r %= i;
if (r < NTYPES2 - NTYPES1)
e->type = &base_types[r + NTYPES1];
r -= NTYPES2 - NTYPES1;
if (e->type == NULL && (features & FEATURE_COMPLEX))
{
if (r < NCTYPES2)
e->type = &complex_types[r];
r -= NCTYPES2;
}
if (e->type == NULL && (features & FEATURE_VECTOR))
{
if (r < NVTYPES2)
e->type = &vector_types[r];
r -= NVTYPES2;
}
if (e->type == NULL)
abort ();
}
static int
my_ffsll (unsigned long long x)
{
int i;
if (x == 0)
return 0;
for (i = 0; i < 64; i++)
if (x & (1ULL << i))
break;
return i + 1;
}
void
generate_fields (enum FEATURE features, struct entry *e, struct entry *parent,
int len)
{
int r, i, j, ret = 1, n, incr, sametype;
for (n = 0; n < len; n += incr)
{
r = generate_random ();
i = (r & 7);
r >>= 3;
incr = 1;
switch (i)
{
case 6:
case 0:
case 1:
case 2:
case 3:
e[n].etype = ETYPE_TYPE;
e[n].type = &base_types[r % NTYPES1];
break;
case 4:
e[n].etype = ETYPE_TYPE;
choose_type (features, &e[n], r, 0);
break;
case 5:
e[n].etype = ETYPE_ARRAY;
i = r & 1;
r >>= 1;
if (i)
e[n].type = &base_types[r % NTYPES1];
else
choose_type (features, &e[n], r, 1);
r = generate_random ();
if ((features & FEATURE_ZEROARRAY) && (r & 3) == 0)
{
e[n].arr_len = 0;
if (n == len - 1 && (r & 4)
&& (parent->etype == ETYPE_STRUCT
|| parent->etype == ETYPE_STRUCT_ARRAY))
{
int k;
for (k = 0; k < n; ++k)
if (e[k].etype != ETYPE_BITFLD || e[k].len)
{
e[n].arr_len = 255;
break;
}
}
}
else if ((r & 3) != 3)
e[n].arr_len = (r >> 2) & 7;
else
e[n].arr_len = (r >> 2) & 31;
break;
#if 0
case 6:
sametype = 1;
switch (r & 7)
{
case 0:
case 1:
case 2:
break;
case 3:
case 4:
case 5:
incr = 1 + (r >> 3) % (len - n);
break;
case 6:
case 7:
sametype = 0;
incr = 1 + (r >> 3) % (len - n);
break;
}
for (j = n; j < n + incr; ++j)
{
int mi, ma;
e[j].etype = ETYPE_BITFLD;
if (j == n || !sametype)
{
r = generate_random ();
r >>= 2;
e[j].type
= &bitfld_types[r % n_bitfld_types];
}
else
e[j].type = e[n].type;
r = generate_random ();
mi = 0;
ma = 0;
switch (e[j].type->bitfld)
{
case 'C': ma = 8; break;
case 'S': ma = 16; break;
case 'I': ma = 32; break;
case 'L':
case 'Q': ma = 64; break;
case 'B': ma = 1; break;
case ' ':
if (e[j].type->type == TYPE_UENUM)
mi = my_ffsll (e[j].type->maxval + 1) - 1;
else if (e[j].type->type == TYPE_SENUM)
mi = my_ffsll (e[j].type->maxval + 1);
else
abort ();
if (!mi)
mi = 1;
if (mi <= 32)
ma = 32;
else
ma = 64;
break;
default:
abort ();
}
e[j].len = ma + 1;
if (sametype && (r & 3) == 0 && ma > 1)
{
int sum = 0, k;
for (k = n; k < j; ++k)
sum += e[k].len;
sum %= ma;
e[j].len = sum ? ma - sum : ma;
}
r >>= 2;
if (! (features & FEATURE_ZEROBITFLD) && mi == 0)
mi = 1;
if (e[j].len < mi || e[j].len > ma)
e[j].len = mi + (r % (ma + 1 - mi));
r >>= 6;
if ((features & FEATURE_ZEROBITFLD) && (r & 3) == 0
&& mi == 0)
e[j].len = 0;
}
break;
#endif
case 7:
switch (r & 7)
{
case 0:
case 1:
case 2:
e[n].etype = ETYPE_STRUCT;
break;
case 3:
case 4:
e[n].etype = ETYPE_UNION;
break;
case 5:
case 6:
e[n].etype = ETYPE_STRUCT_ARRAY;
break;
case 7:
e[n].etype = ETYPE_UNION_ARRAY;
break;
}
r >>= 3;
e[n].len = r % (len - n);
incr = 1 + e[n].len;
generate_fields (features, &e[n + 1], &e[n], e[n].len);
if (e[n].etype == ETYPE_STRUCT_ARRAY
|| e[n].etype == ETYPE_UNION_ARRAY)
{
r = generate_random ();
if ((features & FEATURE_ZEROARRAY) && (r & 3) == 0)
{
e[n].arr_len = 0;
if (n + incr == len && (r & 4)
&& (parent->etype == ETYPE_STRUCT
|| parent->etype == ETYPE_STRUCT_ARRAY))
{
int k;
for (k = 0; k < n; ++k)
if (e[k].etype != ETYPE_BITFLD || e[k].len)
{
e[n].arr_len = 255;
break;
}
}
}
else if ((r & 3) != 3)
e[n].arr_len = (r >> 2) & 7;
else
e[n].arr_len = (r >> 2) & 31;
}
break;
}
}
}
void
generate_random_tests (enum FEATURE features, int len)
{
struct entry e[len + 1];
int i, r;
if (len > 'z' - 'a' + 1)
abort ();
memset (e, 0, sizeof (e));
r = generate_random ();
if ((r & 7) == 0)
e[0].etype = ETYPE_UNION;
else
e[0].etype = ETYPE_STRUCT;
r >>= 3;
e[0].len = len;
generate_fields (features, &e[1], &e[0], len);
output (e);
}
struct { const char *name; enum FEATURE f; }
features[] = {
{ "normal", 0 },
{ "complex", FEATURE_COMPLEX },
{ "vector", FEATURE_VECTOR },
{ "[0] :0", FEATURE_ZEROARRAY | FEATURE_ZEROBITFLD },
{ "complex vector [0]",
FEATURE_COMPLEX | FEATURE_VECTOR | FEATURE_ZEROARRAY }
};
int
main (int argc, char **argv)
{
int i, j, count, c, n = 3000;
char *optarg;
if (sizeof (int) != 4 || sizeof (long long) != 8)
return 1;
i = 1;
while (i < argc)
{
c = '\0';
if (argv[i][0] == '-' && argv[i][2] == '\0')
c = argv[i][1];
optarg = argv[i + 1];
if (!optarg)
goto usage;
switch (c)
{
case 'n':
n = atoi (optarg);
break;
case 'd':
destdir = optarg;
break;
case 's':
srcdir = optarg;
break;
case 'i':
output_one = 1;
limidx = atoi (optarg);
break;
default:
fprintf (stderr, "unrecognized option %s\n", argv[i]);
goto usage;
}
i += 2;
}
if (output_one)
{
outfile = fopen ("/dev/null", "w");
if (outfile == NULL)
{
fputs ("could not open /dev/null", stderr);
return 1;
}
n = limidx + 1;
}
if (destdir == NULL && !output_one)
{
usage:
fprintf (stderr, "Usage:\n\
%s [-s srcdir -d destdir] [-n count] [-i idx]\n\
Either -s srcdir -d destdir or -i idx must be used\n", argv[0]);
return 1;
}
if (srcdir == NULL && !output_one)
goto usage;
for (i = 0; i < NTYPES2; ++i)
if (base_types[i].bitfld)
bitfld_types[n_bitfld_types++] = base_types[i];
for (i = 0; i < sizeof (features) / sizeof (features[0]); ++i)
{
int startidx = idx;
if (! output_one)
limidx = idx;
if (!i)
count = 200;
else
count = 20;
for (j = 1; j <= 9; ++j)
while (idx < startidx + j * count)
generate_random_tests (features[i].f, j);
while (idx < startidx + count * 10)
generate_random_tests (features[i].f, 10 + (generate_random () % 16));
}
for (i = 0; n > 3000 && i < sizeof (features) / sizeof (features[0]); ++i)
{
int startidx;
startidx = idx;
if (! output_one)
limidx = idx;
singles (features[i].f);
if (!i)
{
count = 1000;
while (idx < startidx + 1000)
generate_random_tests (features[i].f, 1);
}
else
{
startidx = idx;
count = 100;
while (idx < startidx + 100)
generate_random_tests (features[i].f, 1);
}
startidx = idx;
for (j = 2; j <= 9; ++j)
while (idx < startidx + (j - 1) * count)
generate_random_tests (features[i].f, j);
while (idx < startidx + count * 9)
generate_random_tests (features[i].f, 10 + (generate_random () % 16));
}
if (! output_one)
limidx = idx;
while (idx < n)
generate_random_tests (ALL_FEATURES, 1 + (generate_random () % 25));
fclose (outfile);
return 0;
}