#include <stdio.h>
#include <stdint.h>

int main() {
    printf("type          size (hex)   size (dec)\n");
    printf("=====================================\n");
#ifdef __PTRADDR_TYPE__
    printf("ptraddr_t     0x%.2lx         %.2lu\n", sizeof(ptraddr_t), sizeof(ptraddr_t));
#endif
    printf("uintptr_t     0x%.2lx         %.2lu\n", sizeof(uintptr_t), sizeof(uintptr_t));
    printf("size_t        0x%.2lx         %.2lu\n", sizeof(size_t), sizeof(size_t));
    printf("void*         0x%.2lx         %.2lu\n", sizeof(void*), sizeof(void*));
    printf("=====================================\n");

#ifdef __CHERI__
    int x = 111;
    int y[] = { 888, 999 };

    int *a = &x;
    int *b = &(y[0]);

    // transplant address from capability a to capability b
    printf("*b: %d\n", *b);
    ptraddr_t a_addr = __builtin_cheri_address_get(a);
    b = __builtin_cheri_address_set(a, a_addr);
    printf("*b: %d\n", *b);

    b = &(y[0]);
    // uintptr_t is an unsigned integer type that preserves capabilities
    uintptr_t b_uintptr = (uintptr_t) b;
    b_uintptr += sizeof(int);
    b = (int*) b_uintptr;
    printf("*b: %d\n", *b);
#endif

    return 0;
}