1 /*------------------------------------------------------------------------- 2 * 3 * relptr.h 4 * This file contains basic declarations for relative pointers. 5 * 6 * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group 7 * Portions Copyright (c) 1994, Regents of the University of California 8 * 9 * src/include/utils/relptr.h 10 * 11 *------------------------------------------------------------------------- 12 */ 13 14 #ifndef RELPTR_H 15 #define RELPTR_H 16 17 /* 18 * Relative pointers are intended to be used when storing an address that may 19 * be relative either to the base of the process's address space or some 20 * dynamic shared memory segment mapped therein. 21 * 22 * The idea here is that you declare a relative pointer as relptr(type) 23 * and then use relptr_access to dereference it and relptr_store to change 24 * it. The use of a union here is a hack, because what's stored in the 25 * relptr is always a Size, never an actual pointer. But including a pointer 26 * in the union allows us to use stupid macro tricks to provide some measure 27 * of type-safety. 28 */ 29 #define relptr(type) union { type *relptr_type; Size relptr_off; } 30 31 /* 32 * pgindent gets confused by declarations that use "relptr(type)" directly, 33 * so preferred style is to write 34 * typedef struct ... SomeStruct; 35 * relptr_declare(SomeStruct, RelptrSomeStruct); 36 * and then declare pointer variables as "RelptrSomeStruct someptr". 37 */ 38 #define relptr_declare(type, relptrtype) \ 39 typedef relptr(type) relptrtype 40 41 #ifdef HAVE__BUILTIN_TYPES_COMPATIBLE_P 42 #define relptr_access(base, rp) \ 43 (AssertVariableIsOfTypeMacro(base, char *), \ 44 (__typeof__((rp).relptr_type)) ((rp).relptr_off == 0 ? NULL : \ 45 (base + (rp).relptr_off))) 46 #else 47 /* 48 * If we don't have __builtin_types_compatible_p, assume we might not have 49 * __typeof__ either. 50 */ 51 #define relptr_access(base, rp) \ 52 (AssertVariableIsOfTypeMacro(base, char *), \ 53 (void *) ((rp).relptr_off == 0 ? NULL : (base + (rp).relptr_off))) 54 #endif 55 56 #define relptr_is_null(rp) \ 57 ((rp).relptr_off == 0) 58 59 #ifdef HAVE__BUILTIN_TYPES_COMPATIBLE_P 60 #define relptr_store(base, rp, val) \ 61 (AssertVariableIsOfTypeMacro(base, char *), \ 62 AssertVariableIsOfTypeMacro(val, __typeof__((rp).relptr_type)), \ 63 (rp).relptr_off = ((val) == NULL ? 0 : ((char *) (val)) - (base))) 64 #else 65 /* 66 * If we don't have __builtin_types_compatible_p, assume we might not have 67 * __typeof__ either. 68 */ 69 #define relptr_store(base, rp, val) \ 70 (AssertVariableIsOfTypeMacro(base, char *), \ 71 (rp).relptr_off = ((val) == NULL ? 0 : ((char *) (val)) - (base))) 72 #endif 73 74 #define relptr_copy(rp1, rp2) \ 75 ((rp1).relptr_off = (rp2).relptr_off) 76 77 #endif /* RELPTR_H */ 78