--- /dev/null
+// bitwise operators
+
+int main(void) {
+ expecti(1 | 2, 3);
+ expecti(2 | 5, 7);
+ expecti(2 | 7, 7);
+
+ expecti(1 & 2, 0);
+ expecti(2 & 7, 2);
+
+ expecti(~0, -1);
+ expecti(~2, -3);
+ expecti(~-1, 0);
+
+ expecti(15 ^ 5, 10);
+
+ expecti(1 << 4, 16);
+ expecti(3 << 4, 48);
+ expecti(15 >> 3, 1);
+ expecti(8 >> 2, 2);
+
+ return 0;
+}
--- /dev/null
+// casts
+
+int main(void) {
+ expecti((int)1, 1);
+ expectf((float)2, 2.0);
+ expectd((double)3, 3.0);
+
+ int a[3];
+ *(int *)(a + 2) = 1024;
+ expecti(a[2], 1024);
+
+ return 0;
+}
--- /dev/null
+// labels as values (computed goto)
+
+int main(void) {
+ // implement a small dispatch table of instructions for a mini
+ // state machine, to test computed goto
+
+ // test state
+ int instruction_0_state = 0;
+ int instruction_1_state = 0;
+ int instruction_2_state = 0;
+
+ unsigned char bytecode[] = {0x01, 0x05, 0x01, 0x02, 0x02, 0x03};
+ unsigned char *pc = bytecode;
+
+ void *dispatch[] = {
+ 0,
+ &&instruction_0,
+ &&instruction_1,
+ &&instruction_2
+ };
+
+ #define DISPATCH(INDEX) \
+ do { \
+ pc += (INDEX); \
+ goto *dispatch[*pc]; \
+ } while (0)
+
+ // machine loop
+ do {
+
+ instruction_0:
+ instruction_0_state += *(pc + 1);
+ DISPATCH(2);
+
+ instruction_1:
+ instruction_1_state ++;
+ DISPATCH(1);
+
+ instruction_2:
+ instruction_2_state --;
+ break;
+
+ } while (1);
+
+ expecti(instruction_0_state, 7);
+ expecti(instruction_1_state, 1);
+ expecti(instruction_2_state, -1);
+
+ return 0;
+}
--- /dev/null
+// comparison
+
+int main(void) {
+ expecti(1 < 2, 1);
+ expecti(1 > 2, 0);
+ expecti(1 == 1, 1);
+ expecti(1 == 2, 0);
+ expecti(1 <= 2, 1);
+ expecti(2 <= 2, 1);
+ expecti(2 <= 1, 0);
+ expecti(1 >= 2, 0);
+ expecti(2 >= 2, 1);
+ expecti(2 >= 1, 1);
+ expecti(1 != 1, 0);
+ expecti(1 != 0, 1);
+ expecti(1.0f == 1.0f, 1);
+ expecti(1.0f == 2.0f, 0);
+ expecti(1.0f != 1.0f, 0);
+ expecti(1.0f != 2.0f, 1);
+ expecti(1.0 == 1.0f, 1);
+ expecti(1.0 == 2.0f, 0);
+ expecti(1.0 != 1.0f, 0);
+ expecti(1.0 != 2.0f, 1);
+ expecti(1.0f == 1.0, 1);
+ expecti(1.0f == 2.0, 0);
+ expecti(1.0f != 1.0, 0);
+ expecti(1.0f != 2.0, 1);
+ expecti(1.0 == 1.0, 1);
+ expecti(1.0 == 2.0, 0);
+ expecti(1.0 != 1.0, 0);
+ expecti(1.0 != 2.0, 1);
+
+ return 0;
+}
--- /dev/null
+// compound assignment
+
+int main(void) {
+ int a = 5;
+ expecti((a += 5), 10);
+ expecti((a -= 5), 5);
+ expecti((a *= 5), 25);
+ expecti((a /= 5), 5);
+ expecti((a %= 3), 2);
+
+ int b = 14;
+ expecti((b &= 7), 6);
+ expecti((b |= 8), 14);
+ expecti((b ^= 3), 13);
+ expecti((b <<= 2), 52);
+ expecti((b >>= 2), 13);
+
+ return 0;
+}
--- /dev/null
+// control flow
+
+int if1(void) {
+ if (1) {
+ return 1;
+ }
+ return 0;
+}
+
+int if2(void) {
+ if (0) {
+ return 0;
+ }
+ return 2;
+}
+
+int if3(void) {
+ if (1) {
+ return 3;
+ } else {
+ return 0;
+ }
+ return 0;
+}
+
+int if4(void) {
+ if (0) {
+ return 0;
+ } else {
+ return 4;
+ }
+ return 0;
+}
+
+int if5(void) {
+ if (1) return 5;
+ return 0;
+}
+
+int if6(void) {
+ if (0) return 0;
+ return 6;
+}
+
+int if7(void) {
+ if (1) return 7;
+ else return 0;
+ return 0;
+}
+
+int if8(void) {
+ if (0) return 0;
+ else return 8;
+ return 0;
+}
+
+int if9(void) {
+ // 0.5 evaluates true
+ if (0.5) return 9;
+ else return 0;
+}
+
+int main(void) {
+ int i;
+ int j;
+
+ expecti(if1(), 1);
+ expecti(if2(), 2);
+ expecti(if3(), 3);
+ expecti(if4(), 4);
+ expecti(if5(), 5);
+ expecti(if6(), 6);
+ expecti(if7(), 7);
+ expecti(if8(), 8);
+ expecti(if9(), 9);
+
+ // for control
+ j = 0;
+ for (i = 0; i < 5; i++)
+ j = j + i;
+ expecti(j, 10);
+
+ j = 0;
+ for (i = 0; i < 5; i++) {
+ j = j + i;
+ }
+ expecti(j, 10);
+
+ j = 0;
+ for (i = 0; i < 100; i++) {
+ if (i < 5)
+ continue;
+ if (i == 9)
+ break;
+ j += i;
+ }
+ expecti(j, 5 + 6 + 7 + 8);
+
+ i = 0;
+ for (; 0.5;) {
+ i = 1337;
+ break;
+ }
+ expecti(i, 1337);
+
+ // while control
+ i = 0;
+ j = 0;
+ while (i <= 100)
+ j = j + i++;
+ expecti(j, 5050);
+
+ i = 0;
+ j = 1;
+ while (i <= 100)
+ j = j + i++;
+ expecti(j, 5051);
+
+ i = 0;
+ j = 0;
+ while (i < 10) {
+ if (i++ < 5)
+ continue;
+ j += i;
+ if (i == 9)
+ break;
+ }
+ expecti(j, 6 + 7 + 8 + 9);
+
+ i = 0;
+ while (0.5) {
+ i = 1337;
+ break;
+ }
+ expecti(i, 1337);
+
+ // do control
+ i = 0;
+ j = 0;
+ do {
+ j = j + i++;
+ } while (i <= 100);
+ expecti(j, 5050);
+
+ i = 0;
+ do { i = 1337; } while (0);
+ expecti(i, 1337);
+
+ i = 0;
+ j = 0;
+ do {
+ if (i++ < 5)
+ continue;
+ j += i;
+ if (i == 9)
+ break;
+ } while (i < 10);
+ expecti(j, 6 + 7 + 8 + 9);
+ expecti(i, 9);
+
+ i = 0;
+ do { i++; break; } while (0.5);
+ expecti(i, 1);
+
+ // switch control
+ i = 0;
+ switch (1 + 2) {
+ case 0:
+ expecti(0, 1);
+ case 3:
+ i = 3;
+ break;
+ case 1:
+ expecti(0, 1);
+ }
+ expecti(i, 3);
+
+ i = 0;
+ switch(1) {
+ case 0: i++;
+ case 1: i++;
+ case 2: i++;
+ case 3: i++;
+ }
+ expecti(i, 3);
+
+ i = 0;
+ switch (1024) {
+ case 0: i++;
+ default:
+ i = 128;
+ }
+ expecti(i, 128);
+
+ i = 0;
+ switch (1024) {
+ case 0: i++;
+ }
+ expecti(i, 0);
+
+ i = 1024;
+ switch (3) {
+ i++;
+ }
+
+ switch (1337) {
+ case 1 ... 100:
+ expecti(1, 0);
+ case 101:
+ expecti(1, 0);
+ case 102 ... 1337:
+ break;
+ default:
+ expecti(1, 0);
+ }
+
+ expecti(i, 1024);
+
+ i = 0;
+ j = 1024;
+ switch (j % 8) {
+ case 0: do { i++;
+ case 7: i++;
+ case 6: i++;
+ case 5: i++;
+ case 4: i++;
+ case 3: i++;
+ case 2: i++;
+ case 1: i++;
+ } while ((j -= 8) > 0);
+ }
+ expecti(i, 1024);
+
+ // goto control
+ j = 0;
+ goto A;
+ j = 5;
+A: expecti(j, 0);
+ i = 0;
+ j = 0;
+B: if (i > 10)
+ goto C;
+ j += i++;
+ goto B;
+C: if (i > 11)
+ goto D;
+ expecti(j, 55);
+ i++;
+ goto B;
+D:
+ expecti(i, 12);
+ expecti(j, 55);
+
+ // logical or control flow
+ expecti(0 || 3, 1);
+ expecti(5 || 0, 1);
+ expecti(0 || 0, 0);
+
+ // empty expressions
+ for (;;)
+ break;
+
+ for (i = 0; i < 50; i++)
+ ;
+
+ i = 0;
+ while (i++ < 50)
+ ;
+
+ i = 0;
+ do 1; while (i++ < 50);
+ i = 0;
+ do; while (i++ < 50);
+
+ switch (1)
+ ;
+
+ i = ((0.5) ? 1 : 0);
+ expecti(i, 1);
+
+ // computed goto
+ void *Q[] = { &&__a, &&__b, &&__c, &&__d };
+ int _ = 0;
+ goto *Q[0];
+ _ = 100;
+
+__a:
+ if (_ == 5)
+ return 0;
+ expecti(_, 0);
+ _ = 1;
+ goto *Q[2];
+ _ = 2;
+
+__b:
+ expecti(_, -1);
+ _ = 5;
+ goto *Q[3];
+ _ = 0;
+
+__c:
+ expecti(_, 1);
+ _ = -1;
+ goto *Q[1];
+ _ = 3;
+
+__d:
+ expecti(_, 5);
+ goto **Q;
+
+
+ return 1; // error
+}
--- /dev/null
+// dynamic loading
+#include <stddef.h>
+
+// should be good for the next ten thousand years :P
+#define SOMAX 128
+
+int main(void) {
+ int so = 0;
+ char buffer[32];
+ void *handle = dlopen("libc.so", 1);
+
+ if (!handle) {
+ for (so = 0; so < SOMAX; so++) {
+ snprintf(buffer, sizeof(buffer), "libc.so.%d", so);
+ if ((handle = dlopen(buffer, 1)))
+ break;
+ }
+ }
+
+ if (!handle) {
+ printf("failed to load libc\n");
+ return 1;
+ }
+
+ // test must return 0 to succeed
+ int (*a)(int) = dlsym(handle, "exit");
+ a(0);
+
+ return 1;
+}
--- /dev/null
+// enumerations
+
+enum {
+ A,
+ B,
+ C
+};
+
+enum {
+ D,
+ E,
+ F
+};
+
+int main(void) {
+ expecti(A, 0);
+ expecti(B, 1);
+ expecti(C, 2);
+ expecti(D, 0);
+ expecti(E, 1);
+ expecti(F, 2);
+
+ enum { G } enum1;
+ enum { H };
+
+ expecti(G, 0);
+ expecti(H, 0);
+
+ enum named {
+ I,
+ J,
+ K
+ };
+
+ enum named enum2 = I;
+ expecti(enum2, 0);
+
+ return 0;
+}
--- /dev/null
+// expression statements
+
+#define maxint(A, B) \
+ ({ int a = (A), b = (B); a > b ? a : b; })
+
+int main(void) {
+
+ expecti(({ 'a'; 1; 64; }), 64);
+
+ expecti(
+ ({
+ int a = 10;
+ a;
+ }), 10
+ );
+
+ expecti(
+ ({
+ int i = 0;
+ for (; i < 10; i++)
+ ;
+ i;
+ }), 10
+ );
+
+ expecti(maxint(100, 5), 100);
+
+ expecti(({ (int){1}; }), 1);
+
+ return 0;
+}
--- /dev/null
+// external linkage
+
+extern int expecti(int, int);
+extern int external_1;
+int extern external_2;
+
+int main(void) {
+ expecti(external_1, 1337);
+ expecti(external_2, 7331);
+
+ return 0;
+}
--- /dev/null
+// floats
+
+float ffunc1(float arg) { return arg; }
+float ffunc2(double arg) { return arg; }
+float ffunc3(int arg) { return arg; }
+double dfunc1(float arg) { return arg; }
+double dfunc2(double arg) { return arg; }
+double dfunc3(int arg) { return arg; }
+
+// deal with recursive calls for floats / doubles
+// requires stack alignment on some architectures
+// to properly work.
+float frecurse(float a) {
+ if (a < 10)
+ return a;
+ return frecurse(3.14);
+}
+
+double drecurse(double a) {
+ if (a < 10)
+ return a;
+ return drecurse(6.28);
+}
+
+int main(void) {
+ // all float
+ expectf(1.0, 1.0);
+ expectf(1.0 + 0.5, 1.5);
+ expectf(1.0 - 0.5, 0.5);
+ expectf(1.0 * 2.0, 2.0);
+ expectf(1.0 / 4.0, 0.25);
+
+ // float and int
+ expectf(1.0, 1.0);
+ expectf(1.0 + 1, 2.0);
+ expectf(1.0 - 1, 0.0);
+ expectf(1.0 * 2, 2.0);
+ expectf(1.0 / 4, 0.25);
+
+ expectf(ffunc1(3.14f), 3.14f);
+ expectf(ffunc1(3.0f), 3.0f);
+ expectf(ffunc2(3.14f), 3.14f);
+ expectf(ffunc2(3.0f), 3.0f);
+ expectf(ffunc3(3.14f), 3.0f);
+ expectf(ffunc3(3), 3);
+ expectd(dfunc1(1.0), 1.0);
+ expectd(dfunc1(10.0), 10.0);
+ expectd(dfunc2(2.0), 2.0);
+ expectd(dfunc2(10), 10.0);
+ expectd(dfunc3(11.5), 11.0);
+ expectd(dfunc3(10), 10.0);
+ // Bug: these are still broken
+ //expectf(frecurse(1024), 3.14);
+ //expectd(drecurse(1024), 6.28);
+ float a = 1024.0f;
+ float b = a;
+ expectf(a, 1024.0f);
+ expectf(b, 1024.0f);
+
+ double c = 2048.0;
+ double d = c;
+ expectd(c, 2048.0);
+ expectd(d, 2048.0);
+
+ expectf(0.7, .7);
+
+ return 0;
+}