Thanks for using Compiler Explorer
Sponsors
Jakt
C++
Ada
Analysis
Android Java
Android Kotlin
Assembly
C
C3
Carbon
C++ (Circle)
CIRCT
Clean
CMake
CMakeScript
COBOL
C++ for OpenCL
MLIR
Cppx
Cppx-Blue
Cppx-Gold
Cpp2-cppfront
Crystal
C#
CUDA C++
D
Dart
Elixir
Erlang
Fortran
F#
GLSL
Go
Haskell
HLSL
Hook
Hylo
IL
ispc
Java
Julia
Kotlin
LLVM IR
LLVM MIR
Modula-2
Nim
Objective-C
Objective-C++
OCaml
OpenCL C
Pascal
Pony
Python
Racket
Ruby
Rust
Snowball
Scala
Solidity
Spice
SPIR-V
Swift
LLVM TableGen
Toit
TypeScript Native
V
Vala
Visual Basic
WASM
Zig
Javascript
GIMPLE
Ygen
c source #1
Output
Compile to binary object
Link to binary
Execute the code
Intel asm syntax
Demangle identifiers
Verbose demangling
Filters
Unused labels
Library functions
Directives
Comments
Horizontal whitespace
Debug intrinsics
Compiler
6502 cc65 2.17
6502 cc65 2.18
6502 cc65 2.19
6502 cc65 trunk
ARM GCC 10.2.0 (linux)
ARM GCC 10.2.1 (none)
ARM GCC 10.3.0 (linux)
ARM GCC 10.3.1 (2021.07 none)
ARM GCC 10.3.1 (2021.10 none)
ARM GCC 10.5.0
ARM GCC 11.1.0 (linux)
ARM GCC 11.2.0 (linux)
ARM GCC 11.2.1 (none)
ARM GCC 11.3.0 (linux)
ARM GCC 11.4.0
ARM GCC 12.1.0 (linux)
ARM GCC 12.2.0 (linux)
ARM GCC 12.3.0
ARM GCC 12.4.0
ARM GCC 13.1.0 (linux)
ARM GCC 13.2.0
ARM GCC 13.2.0 (unknown-eabi)
ARM GCC 13.3.0
ARM GCC 13.3.0 (unknown-eabi)
ARM GCC 14.1.0
ARM GCC 14.1.0 (unknown-eabi)
ARM GCC 14.2.0
ARM GCC 14.2.0 (unknown-eabi)
ARM GCC 4.5.4 (linux)
ARM GCC 4.6.4 (linux)
ARM GCC 5.4 (linux)
ARM GCC 5.4.1 (none)
ARM GCC 6.3.0 (linux)
ARM GCC 6.4.0 (linux)
ARM GCC 7.2.1 (none)
ARM GCC 7.3.0 (linux)
ARM GCC 7.5.0 (linux)
ARM GCC 8.2.0 (WinCE)
ARM GCC 8.2.0 (linux)
ARM GCC 8.3.1 (none)
ARM GCC 8.5.0 (linux)
ARM GCC 9.2.1 (none)
ARM GCC 9.3.0 (linux)
ARM GCC trunk (linux)
ARM msvc v19.0 (WINE)
ARM msvc v19.10 (WINE)
ARM msvc v19.14 (WINE)
ARM64 GCC 10.2.0
ARM64 GCC 10.3.0
ARM64 GCC 10.4.0
ARM64 GCC 10.5.0
ARM64 GCC 11.1.0
ARM64 GCC 11.2.0
ARM64 GCC 11.3.0
ARM64 GCC 11.4.0
ARM64 GCC 12.1.0
ARM64 GCC 12.2.0
ARM64 GCC 12.3.0
ARM64 GCC 12.4.0
ARM64 GCC 13.1.0
ARM64 GCC 13.2.0
ARM64 GCC 13.3.0
ARM64 GCC 14.1.0
ARM64 GCC 14.2.0
ARM64 GCC 4.9.4
ARM64 GCC 5.4
ARM64 GCC 5.5.0
ARM64 GCC 6.3
ARM64 GCC 6.4.0
ARM64 GCC 7.3.0
ARM64 GCC 7.5.0
ARM64 GCC 8.2.0
ARM64 GCC 8.5.0
ARM64 GCC 9.3.0
ARM64 GCC 9.4.0
ARM64 GCC 9.5.0
ARM64 GCC trunk
ARM64 Morello GCC 10.1.0 Alpha 1
ARM64 Morello GCC 10.1.2 Alpha 2
ARM64 msvc v19.14 (WINE)
AVR gcc 10.3.0
AVR gcc 11.1.0
AVR gcc 12.1.0
AVR gcc 12.2.0
AVR gcc 12.3.0
AVR gcc 12.4.0
AVR gcc 13.1.0
AVR gcc 13.2.0
AVR gcc 13.3.0
AVR gcc 14.1.0
AVR gcc 14.2.0
AVR gcc 4.5.4
AVR gcc 4.6.4
AVR gcc 5.4.0
AVR gcc 9.2.0
AVR gcc 9.3.0
Arduino Mega (1.8.9)
Arduino Uno (1.8.9)
BPF clang (trunk)
BPF clang 13.0.0
BPF clang 14.0.0
BPF clang 15.0.0
BPF clang 16.0.0
BPF clang 17.0.1
BPF clang 18.1.0
BPF gcc 13.1.0
BPF gcc 13.2.0
BPF gcc 13.3.0
BPF gcc 14.1.0
BPF gcc 14.2.0
BPF gcc trunk
Chibicc 2020-12-07
FRC 2019
FRC 2020
FRC 2023
HPPA gcc 14.2.0
K1C gcc 7.4
K1C gcc 7.5
KVX ACB 4.1.0 (GCC 7.5.0)
KVX ACB 4.1.0-cd1 (GCC 7.5.0)
KVX ACB 4.10.0 (GCC 10.3.1)
KVX ACB 4.11.1 (GCC 10.3.1)
KVX ACB 4.12.0 (GCC 11.3.0)
KVX ACB 4.2.0 (GCC 7.5.0)
KVX ACB 4.3.0 (GCC 7.5.0)
KVX ACB 4.4.0 (GCC 7.5.0)
KVX ACB 4.6.0 (GCC 9.4.1)
KVX ACB 4.8.0 (GCC 9.4.1)
KVX ACB 4.9.0 (GCC 9.4.1)
KVX ACB 5.0.0 (GCC 12.2.1)
KVX ACB 5.2.0 (GCC 13.2.1)
LC3 (trunk)
M68K clang (trunk)
M68K gcc 13.1.0
M68K gcc 13.2.0
M68K gcc 13.3.0
M68K gcc 14.1.0
M68K gcc 14.2.0
MRISC32 gcc (trunk)
MSP430 gcc 12.1.0
MSP430 gcc 12.2.0
MSP430 gcc 12.3.0
MSP430 gcc 12.4.0
MSP430 gcc 13.1.0
MSP430 gcc 13.2.0
MSP430 gcc 13.3.0
MSP430 gcc 14.1.0
MSP430 gcc 14.2.0
MSP430 gcc 4.5.3
MSP430 gcc 5.3.0
MSP430 gcc 6.2.1
MinGW clang 14.0.3
MinGW clang 14.0.6
MinGW clang 15.0.7
MinGW clang 16.0.0
MinGW clang 16.0.2
MinGW gcc 11.3.0
MinGW gcc 12.1.0
MinGW gcc 12.2.0
MinGW gcc 13.1.0
POWER64 gcc 11.2.0
POWER64 gcc 12.1.0
POWER64 gcc 12.2.0
POWER64 gcc 12.3.0
POWER64 gcc 12.4.0
POWER64 gcc 13.1.0
POWER64 gcc 13.2.0
POWER64 gcc 13.3.0
POWER64 gcc 14.1.0
POWER64 gcc 14.2.0
POWER64 gcc trunk
RISC-V (32-bits) gcc (trunk)
RISC-V (32-bits) gcc 10.2.0
RISC-V (32-bits) gcc 10.3.0
RISC-V (32-bits) gcc 11.2.0
RISC-V (32-bits) gcc 11.3.0
RISC-V (32-bits) gcc 11.4.0
RISC-V (32-bits) gcc 12.1.0
RISC-V (32-bits) gcc 12.2.0
RISC-V (32-bits) gcc 12.3.0
RISC-V (32-bits) gcc 12.4.0
RISC-V (32-bits) gcc 13.1.0
RISC-V (32-bits) gcc 13.2.0
RISC-V (32-bits) gcc 13.3.0
RISC-V (32-bits) gcc 14.1.0
RISC-V (32-bits) gcc 14.2.0
RISC-V (32-bits) gcc 8.2.0
RISC-V (32-bits) gcc 8.5.0
RISC-V (32-bits) gcc 9.4.0
RISC-V (64-bits) gcc (trunk)
RISC-V (64-bits) gcc 10.2.0
RISC-V (64-bits) gcc 10.3.0
RISC-V (64-bits) gcc 11.2.0
RISC-V (64-bits) gcc 11.3.0
RISC-V (64-bits) gcc 11.4.0
RISC-V (64-bits) gcc 12.1.0
RISC-V (64-bits) gcc 12.2.0
RISC-V (64-bits) gcc 12.3.0
RISC-V (64-bits) gcc 12.4.0
RISC-V (64-bits) gcc 13.1.0
RISC-V (64-bits) gcc 13.2.0
RISC-V (64-bits) gcc 13.3.0
RISC-V (64-bits) gcc 14.1.0
RISC-V (64-bits) gcc 14.2.0
RISC-V (64-bits) gcc 8.2.0
RISC-V (64-bits) gcc 8.5.0
RISC-V (64-bits) gcc 9.4.0
RISC-V rv32gc clang (trunk)
RISC-V rv32gc clang 10.0.0
RISC-V rv32gc clang 10.0.1
RISC-V rv32gc clang 11.0.0
RISC-V rv32gc clang 11.0.1
RISC-V rv32gc clang 12.0.0
RISC-V rv32gc clang 12.0.1
RISC-V rv32gc clang 13.0.0
RISC-V rv32gc clang 13.0.1
RISC-V rv32gc clang 14.0.0
RISC-V rv32gc clang 15.0.0
RISC-V rv32gc clang 16.0.0
RISC-V rv32gc clang 17.0.1
RISC-V rv32gc clang 18.1.0
RISC-V rv32gc clang 9.0.0
RISC-V rv32gc clang 9.0.1
RISC-V rv64gc clang (trunk)
RISC-V rv64gc clang 10.0.0
RISC-V rv64gc clang 10.0.1
RISC-V rv64gc clang 11.0.0
RISC-V rv64gc clang 11.0.1
RISC-V rv64gc clang 12.0.0
RISC-V rv64gc clang 12.0.1
RISC-V rv64gc clang 13.0.0
RISC-V rv64gc clang 13.0.1
RISC-V rv64gc clang 14.0.0
RISC-V rv64gc clang 15.0.0
RISC-V rv64gc clang 16.0.0
RISC-V rv64gc clang 17.0.1
RISC-V rv64gc clang 18.1.0
RISC-V rv64gc clang 9.0.0
RISC-V rv64gc clang 9.0.1
Raspbian Buster
Raspbian Stretch
SDCC 4.0.0
SDCC 4.1.0
SDCC 4.2.0
SDCC 4.3.0
SDCC 4.4.0
SPARC LEON gcc 12.2.0
SPARC LEON gcc 12.3.0
SPARC LEON gcc 12.4.0
SPARC LEON gcc 13.1.0
SPARC LEON gcc 13.2.0
SPARC LEON gcc 13.3.0
SPARC LEON gcc 14.1.0
SPARC LEON gcc 14.2.0
SPARC gcc 12.2.0
SPARC gcc 12.3.0
SPARC gcc 12.4.0
SPARC gcc 13.1.0
SPARC gcc 13.2.0
SPARC gcc 13.3.0
SPARC gcc 14.1.0
SPARC gcc 14.2.0
SPARC64 gcc 12.2.0
SPARC64 gcc 12.3.0
SPARC64 gcc 12.4.0
SPARC64 gcc 13.1.0
SPARC64 gcc 13.2.0
SPARC64 gcc 13.3.0
SPARC64 gcc 14.1.0
SPARC64 gcc 14.2.0
TCC (trunk)
TCC 0.9.27
TI C6x gcc 12.2.0
TI C6x gcc 12.3.0
TI C6x gcc 12.4.0
TI C6x gcc 13.1.0
TI C6x gcc 13.2.0
TI C6x gcc 13.3.0
TI C6x gcc 14.1.0
TI C6x gcc 14.2.0
TI CL430 21.6.1
VAX gcc NetBSDELF 10.4.0
VAX gcc NetBSDELF 10.5.0 (Nov 15 03:50:22 2023)
WebAssembly clang (trunk)
Xtensa ESP32 gcc 11.2.0 (2022r1)
Xtensa ESP32 gcc 12.2.0 (20230208)
Xtensa ESP32 gcc 8.2.0 (2019r2)
Xtensa ESP32 gcc 8.2.0 (2020r1)
Xtensa ESP32 gcc 8.2.0 (2020r2)
Xtensa ESP32 gcc 8.4.0 (2020r3)
Xtensa ESP32 gcc 8.4.0 (2021r1)
Xtensa ESP32 gcc 8.4.0 (2021r2)
Xtensa ESP32-S2 gcc 11.2.0 (2022r1)
Xtensa ESP32-S2 gcc 12.2.0 (20230208)
Xtensa ESP32-S2 gcc 8.2.0 (2019r2)
Xtensa ESP32-S2 gcc 8.2.0 (2020r1)
Xtensa ESP32-S2 gcc 8.2.0 (2020r2)
Xtensa ESP32-S2 gcc 8.4.0 (2020r3)
Xtensa ESP32-S2 gcc 8.4.0 (2021r1)
Xtensa ESP32-S2 gcc 8.4.0 (2021r2)
Xtensa ESP32-S3 gcc 11.2.0 (2022r1)
Xtensa ESP32-S3 gcc 12.2.0 (20230208)
Xtensa ESP32-S3 gcc 8.4.0 (2020r3)
Xtensa ESP32-S3 gcc 8.4.0 (2021r1)
Xtensa ESP32-S3 gcc 8.4.0 (2021r2)
arm64 msvc v19.20 VS16.0
arm64 msvc v19.21 VS16.1
arm64 msvc v19.22 VS16.2
arm64 msvc v19.23 VS16.3
arm64 msvc v19.24 VS16.4
arm64 msvc v19.25 VS16.5
arm64 msvc v19.27 VS16.7
arm64 msvc v19.28 VS16.8
arm64 msvc v19.28 VS16.9
arm64 msvc v19.29 VS16.10
arm64 msvc v19.29 VS16.11
arm64 msvc v19.30 VS17.0
arm64 msvc v19.31 VS17.1
arm64 msvc v19.32 VS17.2
arm64 msvc v19.33 VS17.3
arm64 msvc v19.34 VS17.4
arm64 msvc v19.35 VS17.5
arm64 msvc v19.36 VS17.6
arm64 msvc v19.37 VS17.7
arm64 msvc v19.38 VS17.8
arm64 msvc v19.39 VS17.9
arm64 msvc v19.40 VS17.10
arm64 msvc v19.latest
armv7-a clang (trunk)
armv7-a clang 10.0.0
armv7-a clang 10.0.1
armv7-a clang 11.0.0
armv7-a clang 11.0.1
armv7-a clang 12.0.0
armv7-a clang 12.0.1
armv7-a clang 13.0.0
armv7-a clang 13.0.1
armv7-a clang 14.0.0
armv7-a clang 15.0.0
armv7-a clang 16.0.0
armv7-a clang 17.0.1
armv7-a clang 18.1.0
armv7-a clang 9.0.0
armv7-a clang 9.0.1
armv8-a clang (all architectural features, trunk)
armv8-a clang (trunk)
armv8-a clang 10.0.0
armv8-a clang 10.0.1
armv8-a clang 11.0.0
armv8-a clang 11.0.1
armv8-a clang 12.0.0
armv8-a clang 12.0.1
armv8-a clang 13.0.0
armv8-a clang 13.0.1
armv8-a clang 14.0.0
armv8-a clang 15.0.0
armv8-a clang 16.0.0
armv8-a clang 17.0.1
armv8-a clang 18.1.0
armv8-a clang 9.0.0
armv8-a clang 9.0.1
clang 12 for DPU (rel 2023.2.0)
cproc-master
llvm-mos commander X16
llvm-mos commodore 64
llvm-mos mega65
llvm-mos nes-cnrom
llvm-mos nes-mmc1
llvm-mos nes-mmc3
llvm-mos nes-nrom
llvm-mos osi-c1p
loongarch64 gcc 12.2.0
loongarch64 gcc 12.3.0
loongarch64 gcc 12.4.0
loongarch64 gcc 13.1.0
loongarch64 gcc 13.2.0
loongarch64 gcc 13.3.0
loongarch64 gcc 14.1.0
loongarch64 gcc 14.2.0
mips (el) gcc 12.1.0
mips (el) gcc 12.2.0
mips (el) gcc 12.3.0
mips (el) gcc 12.4.0
mips (el) gcc 13.1.0
mips (el) gcc 13.2.0
mips (el) gcc 13.3.0
mips (el) gcc 14.1.0
mips (el) gcc 14.2.0
mips (el) gcc 4.9.4
mips (el) gcc 5.4
mips (el) gcc 5.5.0
mips (el) gcc 9.5.0
mips clang 13.0.0
mips clang 14.0.0
mips clang 15.0.0
mips clang 16.0.0
mips clang 17.0.1
mips clang 18.1.0
mips gcc 11.2.0
mips gcc 12.1.0
mips gcc 12.2.0
mips gcc 12.3.0
mips gcc 12.4.0
mips gcc 13.1.0
mips gcc 13.2.0
mips gcc 13.3.0
mips gcc 14.1.0
mips gcc 14.2.0
mips gcc 4.9.4
mips gcc 5.4
mips gcc 5.5.0
mips gcc 9.3.0 (codescape)
mips gcc 9.5.0
mips64 (el) gcc 12.1.0
mips64 (el) gcc 12.2.0
mips64 (el) gcc 12.3.0
mips64 (el) gcc 12.4.0
mips64 (el) gcc 13.1.0
mips64 (el) gcc 13.2.0
mips64 (el) gcc 13.3.0
mips64 (el) gcc 14.1.0
mips64 (el) gcc 14.2.0
mips64 (el) gcc 4.9.4
mips64 (el) gcc 5.4.0
mips64 (el) gcc 5.5.0
mips64 (el) gcc 9.5.0
mips64 clang 13.0.0
mips64 clang 14.0.0
mips64 clang 15.0.0
mips64 clang 16.0.0
mips64 clang 17.0.1
mips64 clang 18.1.0
mips64 gcc 11.2.0
mips64 gcc 12.1.0
mips64 gcc 12.2.0
mips64 gcc 12.3.0
mips64 gcc 12.4.0
mips64 gcc 13.1.0
mips64 gcc 13.2.0
mips64 gcc 13.3.0
mips64 gcc 14.1.0
mips64 gcc 14.2.0
mips64 gcc 4.9.4
mips64 gcc 5.4
mips64 gcc 5.5.0
mips64 gcc 9.5.0
mips64el clang 13.0.0
mips64el clang 14.0.0
mips64el clang 15.0.0
mips64el clang 16.0.0
mips64el clang 17.0.1
mips64el clang 18.1.0
mipsel clang 13.0.0
mipsel clang 14.0.0
mipsel clang 15.0.0
mipsel clang 16.0.0
mipsel clang 17.0.1
mipsel clang 18.1.0
movfuscator (trunk)
nanoMIPS gcc 6.3.0
power gcc 11.2.0
power gcc 12.1.0
power gcc 12.2.0
power gcc 12.3.0
power gcc 12.4.0
power gcc 13.1.0
power gcc 13.2.0
power gcc 13.3.0
power gcc 14.1.0
power gcc 14.2.0
power gcc 4.8.5
power64 AT12.0 (gcc8)
power64 AT13.0 (gcc9)
power64le AT12.0 (gcc8)
power64le AT13.0 (gcc9)
power64le clang (trunk)
power64le gcc 11.2.0
power64le gcc 12.1.0
power64le gcc 12.2.0
power64le gcc 12.3.0
power64le gcc 12.4.0
power64le gcc 13.1.0
power64le gcc 13.2.0
power64le gcc 13.3.0
power64le gcc 14.1.0
power64le gcc 14.2.0
power64le gcc 6.3.0
power64le gcc trunk
powerpc64 clang (trunk)
ppci 0.5.5
s390x gcc 11.2.0
s390x gcc 12.1.0
s390x gcc 12.2.0
s390x gcc 12.3.0
s390x gcc 12.4.0
s390x gcc 13.1.0
s390x gcc 13.2.0
s390x gcc 13.3.0
s390x gcc 14.1.0
s390x gcc 14.2.0
sh gcc 12.2.0
sh gcc 12.3.0
sh gcc 12.4.0
sh gcc 13.1.0
sh gcc 13.2.0
sh gcc 13.3.0
sh gcc 14.1.0
sh gcc 14.2.0
sh gcc 4.9.4
sh gcc 9.5.0
vast (trunk)
x64 msvc v19.0 (WINE)
x64 msvc v19.10 (WINE)
x64 msvc v19.14 (WINE)
x64 msvc v19.20 VS16.0
x64 msvc v19.21 VS16.1
x64 msvc v19.22 VS16.2
x64 msvc v19.23 VS16.3
x64 msvc v19.24 VS16.4
x64 msvc v19.25 VS16.5
x64 msvc v19.27 VS16.7
x64 msvc v19.28 VS16.8
x64 msvc v19.28 VS16.9
x64 msvc v19.29 VS16.10
x64 msvc v19.29 VS16.11
x64 msvc v19.30 VS17.0
x64 msvc v19.31 VS17.1
x64 msvc v19.32 VS17.2
x64 msvc v19.33 VS17.3
x64 msvc v19.34 VS17.4
x64 msvc v19.35 VS17.5
x64 msvc v19.36 VS17.6
x64 msvc v19.37 VS17.7
x64 msvc v19.38 VS17.8
x64 msvc v19.39 VS17.9
x64 msvc v19.40 VS17.10
x64 msvc v19.latest
x86 CompCert 3.10
x86 CompCert 3.11
x86 CompCert 3.12
x86 CompCert 3.9
x86 gcc 1.27
x86 msvc v19.0 (WINE)
x86 msvc v19.10 (WINE)
x86 msvc v19.14 (WINE)
x86 msvc v19.20 VS16.0
x86 msvc v19.21 VS16.1
x86 msvc v19.22 VS16.2
x86 msvc v19.23 VS16.3
x86 msvc v19.24 VS16.4
x86 msvc v19.25 VS16.5
x86 msvc v19.27 VS16.7
x86 msvc v19.28 VS16.8
x86 msvc v19.28 VS16.9
x86 msvc v19.29 VS16.10
x86 msvc v19.29 VS16.11
x86 msvc v19.30 VS17.0
x86 msvc v19.31 VS17.1
x86 msvc v19.32 VS17.2
x86 msvc v19.33 VS17.3
x86 msvc v19.34 VS17.4
x86 msvc v19.35 VS17.5
x86 msvc v19.36 VS17.6
x86 msvc v19.37 VS17.7
x86 msvc v19.38 VS17.8
x86 msvc v19.39 VS17.9
x86 msvc v19.40 VS17.10
x86 msvc v19.latest
x86 nvc 24.9
x86 tendra (trunk)
x86-64 clang (assertions trunk)
x86-64 clang (thephd.dev)
x86-64 clang (trunk)
x86-64 clang (widberg)
x86-64 clang 10.0.0
x86-64 clang 10.0.1
x86-64 clang 11.0.0
x86-64 clang 11.0.1
x86-64 clang 12.0.0
x86-64 clang 12.0.1
x86-64 clang 13.0.0
x86-64 clang 13.0.1
x86-64 clang 14.0.0
x86-64 clang 15.0.0
x86-64 clang 16.0.0
x86-64 clang 17.0.1
x86-64 clang 18.1.0
x86-64 clang 19.1.0
x86-64 clang 3.0.0
x86-64 clang 3.1
x86-64 clang 3.2
x86-64 clang 3.3
x86-64 clang 3.4.1
x86-64 clang 3.5
x86-64 clang 3.5.1
x86-64 clang 3.5.2
x86-64 clang 3.6
x86-64 clang 3.7
x86-64 clang 3.7.1
x86-64 clang 3.8
x86-64 clang 3.8.1
x86-64 clang 3.9.0
x86-64 clang 3.9.1
x86-64 clang 4.0.0
x86-64 clang 4.0.1
x86-64 clang 5.0.0
x86-64 clang 5.0.1
x86-64 clang 5.0.2
x86-64 clang 6.0.0
x86-64 clang 6.0.1
x86-64 clang 7.0.0
x86-64 clang 7.0.1
x86-64 clang 7.1.0
x86-64 clang 8.0.0
x86-64 clang 8.0.1
x86-64 clang 9.0.0
x86-64 clang 9.0.1
x86-64 gcc (trunk)
x86-64 gcc 10.1
x86-64 gcc 10.2
x86-64 gcc 10.3
x86-64 gcc 10.4
x86-64 gcc 10.5
x86-64 gcc 11.1
x86-64 gcc 11.2
x86-64 gcc 11.3
x86-64 gcc 11.4
x86-64 gcc 12.1
x86-64 gcc 12.2
x86-64 gcc 12.3
x86-64 gcc 12.4
x86-64 gcc 13.1
x86-64 gcc 13.2
x86-64 gcc 13.3
x86-64 gcc 14.1
x86-64 gcc 14.2
x86-64 gcc 3.4.6
x86-64 gcc 4.0.4
x86-64 gcc 4.1.2
x86-64 gcc 4.4.7
x86-64 gcc 4.5.3
x86-64 gcc 4.6.4
x86-64 gcc 4.7.1
x86-64 gcc 4.7.2
x86-64 gcc 4.7.3
x86-64 gcc 4.7.4
x86-64 gcc 4.8.1
x86-64 gcc 4.8.2
x86-64 gcc 4.8.3
x86-64 gcc 4.8.4
x86-64 gcc 4.8.5
x86-64 gcc 4.9.0
x86-64 gcc 4.9.1
x86-64 gcc 4.9.2
x86-64 gcc 4.9.3
x86-64 gcc 4.9.4
x86-64 gcc 5.1
x86-64 gcc 5.2
x86-64 gcc 5.3
x86-64 gcc 5.4
x86-64 gcc 6.1
x86-64 gcc 6.2
x86-64 gcc 6.3
x86-64 gcc 6.5
x86-64 gcc 7.1
x86-64 gcc 7.2
x86-64 gcc 7.3
x86-64 gcc 7.4
x86-64 gcc 7.5
x86-64 gcc 8.1
x86-64 gcc 8.2
x86-64 gcc 8.3
x86-64 gcc 8.4
x86-64 gcc 8.5
x86-64 gcc 9.1
x86-64 gcc 9.2
x86-64 gcc 9.3
x86-64 gcc 9.4
x86-64 gcc 9.5
x86-64 icc 13.0.1
x86-64 icc 16.0.3
x86-64 icc 17.0.0
x86-64 icc 18.0.0
x86-64 icc 19.0.0
x86-64 icc 19.0.1
x86-64 icc 2021.1.2
x86-64 icc 2021.10.0
x86-64 icc 2021.2.0
x86-64 icc 2021.3.0
x86-64 icc 2021.4.0
x86-64 icc 2021.5.0
x86-64 icc 2021.6.0
x86-64 icc 2021.7.0
x86-64 icc 2021.7.1
x86-64 icc 2021.8.0
x86-64 icc 2021.9.0
x86-64 icx (latest)
x86-64 icx 2021.1.2
x86-64 icx 2021.2.0
x86-64 icx 2021.3.0
x86-64 icx 2021.4.0
x86-64 icx 2022.0.0
x86-64 icx 2022.1.0
x86-64 icx 2022.2.0
x86-64 icx 2022.2.1
x86-64 icx 2023.0.0
x86-64 icx 2023.1.0
x86-64 icx 2024.0.0
x86_64 CompCert 3.10
x86_64 CompCert 3.11
x86_64 CompCert 3.12
x86_64 CompCert 3.9
z88dk 2.2
zig cc 0.10.0
zig cc 0.11.0
zig cc 0.12.0
zig cc 0.12.1
zig cc 0.13.0
zig cc 0.6.0
zig cc 0.7.0
zig cc 0.7.1
zig cc 0.8.0
zig cc 0.9.0
zig cc trunk
Options
Source code
// Type your code here, or load an example. #include <stdbool.h> #include <stdint.h> /* * * nodes.h * Definitions for tagged nodes. * * * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/nodes/nodes.h * *------------------------------------------------------------------------- */ #ifndef NODES_H #define NODES_H /* * The first field of every node is NodeTag. Each node created (with makeNode) * will have one of the following tags as the value of its first field. * * Note that inserting or deleting node types changes the numbers of other * node types later in the list. This is no problem during development, since * the node numbers are never stored on disk. But don't do it in a released * branch, because that would represent an ABI break for extensions. */ typedef enum NodeTag { T_Invalid = 0, } NodeTag; /* * pg_node_attr() - Used in node definitions to set extra information for * gen_node_support.pl * * Attributes can be attached to a node as a whole (place the attribute * specification on the first line after the struct's opening brace) * or to a specific field (place it at the end of that field's line). The * argument is a comma-separated list of attributes. Unrecognized attributes * cause an error. * * Valid node attributes: * * - abstract: Abstract types are types that cannot be instantiated but that * can be supertypes of other types. We track their fields, so that * subtypes can use them, but we don't emit a node tag, so you can't * instantiate them. * * - custom_copy_equal: Has custom implementations in copyfuncs.c and * equalfuncs.c. * * - custom_read_write: Has custom implementations in outfuncs.c and * readfuncs.c. * * - custom_query_jumble: Has custom implementation in queryjumblefuncs.c. * * - no_copy: Does not support copyObject() at all. * * - no_equal: Does not support equal() at all. * * - no_copy_equal: Shorthand for both no_copy and no_equal. * * - no_query_jumble: Does not support JumbleQuery() at all. * * - no_read: Does not support nodeRead() at all. * * - nodetag_only: Does not support copyObject(), equal(), jumbleQuery() * outNode() or nodeRead(). * * - special_read_write: Has special treatment in outNode() and nodeRead(). * * - nodetag_number(VALUE): assign the specified nodetag number instead of * an auto-generated number. Typically this would only be used in stable * branches, to give a newly-added node type a number without breaking ABI * by changing the numbers of existing node types. * * Node types can be supertypes of other types whether or not they are marked * abstract: if a node struct appears as the first field of another struct * type, then it is the supertype of that type. The no_copy, no_equal, * no_query_jumble and no_read node attributes are automatically inherited * from the supertype. (Notice that nodetag_only does not inherit, so it's * not quite equivalent to a combination of other attributes.) * * Valid node field attributes: * * - array_size(OTHERFIELD): This field is a dynamically allocated array with * size indicated by the mentioned other field. The other field is either a * scalar or a list, in which case the length of the list is used. * * - copy_as(VALUE): In copyObject(), replace the field's value with VALUE. * * - copy_as_scalar: In copyObject(), copy the field as a scalar value * (e.g. a pointer) even if it is a node-type pointer. * * - equal_as_scalar: In equal(), compare the field as a scalar value * even if it is a node-type pointer. * * - equal_ignore: Ignore the field for equality. * * - equal_ignore_if_zero: Ignore the field for equality if it is zero. * (Otherwise, compare normally.) * * - query_jumble_ignore: Ignore the field for the query jumbling. Note * that typmod and collation information are usually irrelevant for the * query jumbling. * * - query_jumble_location: Mark the field as a location to track. This is * only allowed for integer fields that include "location" in their name. * * - read_as(VALUE): In nodeRead(), replace the field's value with VALUE. * * - read_write_ignore: Ignore the field for read/write. This is only allowed * if the node type is marked no_read or read_as() is also specified. * * - write_only_relids, write_only_nondefault_pathtarget, write_only_req_outer: * Special handling for Path struct; see there. * */ #define pg_node_attr(...) /* * The first field of a node of any type is guaranteed to be the NodeTag. * Hence the type of any node can be gotten by casting it to Node. Declaring * a variable to be of Node * (instead of void *) can also facilitate * debugging. */ typedef struct Node { NodeTag type; } Node; #define nodeTag(nodeptr) (((const Node*)(nodeptr))->type) /* * newNode - * create a new node of the specified size and tag the node with the * specified tag. * * !WARNING!: Avoid using newNode directly. You should be using the * macro makeNode. eg. to create a Query node, use makeNode(Query) * * Note: the size argument should always be a compile-time constant, so the * apparent risk of multiple evaluation doesn't matter in practice. */ #ifdef __GNUC__ /* With GCC, we can use a compound statement within an expression */ #define newNode(size, tag) \ ({ Node *_result; \ AssertMacro((size) >= sizeof(Node)); /* need the tag, at least */ \ _result = (Node *) palloc0fast(size); \ _result->type = (tag); \ _result; \ }) #else /* * There is no way to dereference the palloc'ed pointer to assign the * tag, and also return the pointer itself, so we need a holder variable. * Fortunately, this macro isn't recursive so we just define * a global variable for this purpose. */ extern PGDLLIMPORT Node *newNodeMacroHolder; #define newNode(size, tag) \ ( \ AssertMacro((size) >= sizeof(Node)), /* need the tag, at least */ \ newNodeMacroHolder = (Node *) palloc0fast(size), \ newNodeMacroHolder->type = (tag), \ newNodeMacroHolder \ ) #endif /* __GNUC__ */ #define makeNode(_type_) ((_type_ *) newNode(sizeof(_type_),T_##_type_)) #define NodeSetTag(nodeptr,t) (((Node*)(nodeptr))->type = (t)) #define IsA(nodeptr,_type_) (nodeTag(nodeptr) == T_##_type_) /* * castNode(type, ptr) casts ptr to "type *", and if assertions are enabled, * verifies that the node has the appropriate type (using its nodeTag()). * * Use an inline function when assertions are enabled, to avoid multiple * evaluations of the ptr argument (which could e.g. be a function call). */ #ifdef USE_ASSERT_CHECKING static inline Node * castNodeImpl(NodeTag type, void *ptr) { Assert(ptr == NULL || nodeTag(ptr) == type); return (Node *) ptr; } #define castNode(_type_, nodeptr) ((_type_ *) castNodeImpl(T_##_type_, nodeptr)) #else #define castNode(_type_, nodeptr) ((_type_ *) (nodeptr)) #endif /* USE_ASSERT_CHECKING */ /* ---------------------------------------------------------------- * extern declarations follow * ---------------------------------------------------------------- */ /* * nodes/{outfuncs.c,print.c} */ struct Bitmapset; /* not to include bitmapset.h here */ struct StringInfoData; /* not to include stringinfo.h here */ extern void outNode(struct StringInfoData *str, const void *obj); extern void outToken(struct StringInfoData *str, const char *s); extern void outBitmapset(struct StringInfoData *str, const struct Bitmapset *bms); extern void outDatum(struct StringInfoData *str, uintptr_t value, int typlen, bool typbyval); extern char *nodeToString(const void *obj); extern char *bmsToString(const struct Bitmapset *bms); /* * nodes/{readfuncs.c,read.c} */ extern void *stringToNode(const char *str); #ifdef WRITE_READ_PARSE_PLAN_TREES extern void *stringToNodeWithLocations(const char *str); #endif extern struct Bitmapset *readBitmapset(void); extern uintptr_t readDatum(bool typbyval); extern bool *readBoolCols(int numCols); extern int *readIntCols(int numCols); /* * nodes/copyfuncs.c */ extern void *copyObjectImpl(const void *from); /* cast result back to argument type, if supported by compiler */ #ifdef HAVE_TYPEOF #define copyObject(obj) ((typeof(obj)) copyObjectImpl(obj)) #else #define copyObject(obj) copyObjectImpl(obj) #endif /* * nodes/equalfuncs.c */ extern bool equal(const void *a, const void *b); /* * Typedefs for identifying qualifier selectivities and plan costs as such. * These are just plain "double"s, but declaring a variable as Selectivity * or Cost makes the intent more obvious. * * These could have gone into plannodes.h or some such, but many files * depend on them... */ typedef double Selectivity; /* fraction of tuples a qualifier will pass */ typedef double Cost; /* execution cost (in page-access units) */ typedef double Cardinality; /* (estimated) number of rows or other integer * count */ /* * CmdType - * enums for type of operation represented by a Query or PlannedStmt * * This is needed in both parsenodes.h and plannodes.h, so put it here... */ typedef enum CmdType { CMD_UNKNOWN, CMD_SELECT, /* select stmt */ CMD_UPDATE, /* update stmt */ CMD_INSERT, /* insert stmt */ CMD_DELETE, /* delete stmt */ CMD_MERGE, /* merge stmt */ CMD_UTILITY, /* cmds like create, destroy, copy, vacuum, * etc. */ CMD_NOTHING /* dummy command for instead nothing rules * with qual */ } CmdType; /* * JoinType - * enums for types of relation joins * * JoinType determines the exact semantics of joining two relations using * a matching qualification. For example, it tells what to do with a tuple * that has no match in the other relation. * * This is needed in both parsenodes.h and plannodes.h, so put it here... */ typedef enum JoinType { /* * The canonical kinds of joins according to the SQL JOIN syntax. Only * these codes can appear in parser output (e.g., JoinExpr nodes). */ JOIN_INNER, /* matching tuple pairs only */ JOIN_LEFT, /* pairs + unmatched LHS tuples */ JOIN_FULL, /* pairs + unmatched LHS + unmatched RHS */ JOIN_RIGHT, /* pairs + unmatched RHS tuples */ /* * Semijoins and anti-semijoins (as defined in relational theory) do not * appear in the SQL JOIN syntax, but there are standard idioms for * representing them (e.g., using EXISTS). The planner recognizes these * cases and converts them to joins. So the planner and executor must * support these codes. NOTE: in JOIN_SEMI output, it is unspecified * which matching RHS row is joined to. In JOIN_ANTI output, the row is * guaranteed to be null-extended. */ JOIN_SEMI, /* 1 copy of each LHS row that has match(es) */ JOIN_ANTI, /* 1 copy of each LHS row that has no match */ JOIN_RIGHT_ANTI, /* 1 copy of each RHS row that has no match */ /* * These codes are used internally in the planner, but are not supported * by the executor (nor, indeed, by most of the planner). */ JOIN_UNIQUE_OUTER, /* LHS path must be made unique */ JOIN_UNIQUE_INNER /* RHS path must be made unique */ /* * We might need additional join types someday. */ } JoinType; /* * OUTER joins are those for which pushed-down quals must behave differently * from the join's own quals. This is in fact everything except INNER and * SEMI joins. However, this macro must also exclude the JOIN_UNIQUE symbols * since those are temporary proxies for what will eventually be an INNER * join. * * Note: semijoins are a hybrid case, but we choose to treat them as not * being outer joins. This is okay principally because the SQL syntax makes * it impossible to have a pushed-down qual that refers to the inner relation * of a semijoin; so there is no strong need to distinguish join quals from * pushed-down quals. This is convenient because for almost all purposes, * quals attached to a semijoin can be treated the same as innerjoin quals. */ #define IS_OUTER_JOIN(jointype) \ (((1 << (jointype)) & \ ((1 << JOIN_LEFT) | \ (1 << JOIN_FULL) | \ (1 << JOIN_RIGHT) | \ (1 << JOIN_ANTI) | \ (1 << JOIN_RIGHT_ANTI))) != 0) /* * AggStrategy - * overall execution strategies for Agg plan nodes * * This is needed in both pathnodes.h and plannodes.h, so put it here... */ typedef enum AggStrategy { AGG_PLAIN, /* simple agg across all input rows */ AGG_SORTED, /* grouped agg, input must be sorted */ AGG_HASHED, /* grouped agg, use internal hashtable */ AGG_MIXED /* grouped agg, hash and sort both used */ } AggStrategy; /* * AggSplit - * splitting (partial aggregation) modes for Agg plan nodes * * This is needed in both pathnodes.h and plannodes.h, so put it here... */ /* Primitive options supported by nodeAgg.c: */ #define AGGSPLITOP_COMBINE 0x01 /* substitute combinefn for transfn */ #define AGGSPLITOP_SKIPFINAL 0x02 /* skip finalfn, return state as-is */ #define AGGSPLITOP_SERIALIZE 0x04 /* apply serialfn to output */ #define AGGSPLITOP_DESERIALIZE 0x08 /* apply deserialfn to input */ /* Supported operating modes (i.e., useful combinations of these options): */ typedef enum AggSplit { /* Basic, non-split aggregation: */ AGGSPLIT_SIMPLE = 0, /* Initial phase of partial aggregation, with serialization: */ AGGSPLIT_INITIAL_SERIAL = AGGSPLITOP_SKIPFINAL | AGGSPLITOP_SERIALIZE, /* Final phase of partial aggregation, with deserialization: */ AGGSPLIT_FINAL_DESERIAL = AGGSPLITOP_COMBINE | AGGSPLITOP_DESERIALIZE } AggSplit; /* Test whether an AggSplit value selects each primitive option: */ #define DO_AGGSPLIT_COMBINE(as) (((as) & AGGSPLITOP_COMBINE) != 0) #define DO_AGGSPLIT_SKIPFINAL(as) (((as) & AGGSPLITOP_SKIPFINAL) != 0) #define DO_AGGSPLIT_SERIALIZE(as) (((as) & AGGSPLITOP_SERIALIZE) != 0) #define DO_AGGSPLIT_DESERIALIZE(as) (((as) & AGGSPLITOP_DESERIALIZE) != 0) /* * SetOpCmd and SetOpStrategy - * overall semantics and execution strategies for SetOp plan nodes * * This is needed in both pathnodes.h and plannodes.h, so put it here... */ typedef enum SetOpCmd { SETOPCMD_INTERSECT, SETOPCMD_INTERSECT_ALL, SETOPCMD_EXCEPT, SETOPCMD_EXCEPT_ALL } SetOpCmd; typedef enum SetOpStrategy { SETOP_SORTED, /* input must be sorted */ SETOP_HASHED /* use internal hashtable */ } SetOpStrategy; /* * OnConflictAction - * "ON CONFLICT" clause type of query * * This is needed in both parsenodes.h and plannodes.h, so put it here... */ typedef enum OnConflictAction { ONCONFLICT_NONE, /* No "ON CONFLICT" clause */ ONCONFLICT_NOTHING, /* ON CONFLICT ... DO NOTHING */ ONCONFLICT_UPDATE /* ON CONFLICT ... DO UPDATE */ } OnConflictAction; /* * LimitOption - * LIMIT option of query * * This is needed in both parsenodes.h and plannodes.h, so put it here... */ typedef enum LimitOption { LIMIT_OPTION_COUNT, /* FETCH FIRST... ONLY */ LIMIT_OPTION_WITH_TIES, /* FETCH FIRST... WITH TIES */ LIMIT_OPTION_DEFAULT, /* No limit present */ } LimitOption; #endif /* NODES_H */ /*------------------------------------------------------------------------- * * postgres_ext.h * * This file contains declarations of things that are visible everywhere * in PostgreSQL *and* are visible to clients of frontend interface libraries. * For example, the Oid type is part of the API of libpq and other libraries. * * Declarations which are specific to a particular interface should * go in the header file for that interface (such as libpq-fe.h). This * file is only for fundamental Postgres declarations. * * User-written C functions don't count as "external to Postgres." * Those function much as local modifications to the backend itself, and * use header files that are otherwise internal to Postgres to interface * with the backend. * * src/include/postgres_ext.h * *------------------------------------------------------------------------- */ #ifndef POSTGRES_EXT_H #define POSTGRES_EXT_H /* * Object ID is a fundamental type in Postgres. */ typedef unsigned int Oid; #ifdef __cplusplus #define InvalidOid (Oid(0)) #else #define InvalidOid ((Oid) 0) #endif #define OID_MAX UINT_MAX /* you will need to include <limits.h> to use the above #define */ #define atooid(x) ((Oid) strtoul((x), NULL, 10)) /* the above needs <stdlib.h> */ /* * Identifiers of error message fields. Kept here to keep common * between frontend and backend, and also to export them to libpq * applications. */ #define PG_DIAG_SEVERITY 'S' #define PG_DIAG_SEVERITY_NONLOCALIZED 'V' #define PG_DIAG_SQLSTATE 'C' #define PG_DIAG_MESSAGE_PRIMARY 'M' #define PG_DIAG_MESSAGE_DETAIL 'D' #define PG_DIAG_MESSAGE_HINT 'H' #define PG_DIAG_STATEMENT_POSITION 'P' #define PG_DIAG_INTERNAL_POSITION 'p' #define PG_DIAG_INTERNAL_QUERY 'q' #define PG_DIAG_CONTEXT 'W' #define PG_DIAG_SCHEMA_NAME 's' #define PG_DIAG_TABLE_NAME 't' #define PG_DIAG_COLUMN_NAME 'c' #define PG_DIAG_DATATYPE_NAME 'd' #define PG_DIAG_CONSTRAINT_NAME 'n' #define PG_DIAG_SOURCE_FILE 'F' #define PG_DIAG_SOURCE_LINE 'L' #define PG_DIAG_SOURCE_FUNCTION 'R' #endif /* POSTGRES_EXT_H */ /*------------------------------------------------------------------------- * * c.h * Fundamental C definitions. This is included by every .c file in * PostgreSQL (via either postgres.h or postgres_fe.h, as appropriate). * * Note that the definitions here are not intended to be exposed to clients * of the frontend interface libraries --- so we don't worry much about * polluting the namespace with lots of stuff... * * * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/c.h * *------------------------------------------------------------------------- */ /* *---------------------------------------------------------------- * TABLE OF CONTENTS * * When adding stuff to this file, please try to put stuff * into the relevant section, or add new sections as appropriate. * * section description * ------- ------------------------------------------------ * 0) pg_config.h and standard system headers * 1) compiler characteristics * 2) bool, true, false * 3) standard system types * 4) IsValid macros for system types * 5) lengthof, alignment * 6) assertions * 7) widely useful macros * 8) random stuff * 9) system-specific hacks * * NOTE: since this file is included by both frontend and backend modules, * it's usually wrong to put an "extern" declaration here, unless it's * ifdef'd so that it's seen in only one case or the other. * typedefs and macros are the kind of thing that might go here. * *---------------------------------------------------------------- */ #ifndef C_H #define C_H /* System header files that should be available everywhere in Postgres */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stddef.h> #include <stdarg.h> #ifdef HAVE_STRINGS_H #include <strings.h> #endif #include <stdint.h> #include <sys/types.h> #include <errno.h> #if defined(WIN32) || defined(__CYGWIN__) #include <fcntl.h> /* ensure O_BINARY is available */ #endif #include <locale.h> #ifdef ENABLE_NLS #include <libintl.h> #endif /* Define before including zlib.h to add const decorations to zlib API. */ #ifdef HAVE_LIBZ #define ZLIB_CONST #endif /* ---------------------------------------------------------------- * Section 1: compiler characteristics * * type prefixes (const, signed, volatile, inline) are handled in pg_config.h. * ---------------------------------------------------------------- */ /* * Disable "inline" if PG_FORCE_DISABLE_INLINE is defined. * This is used to work around compiler bugs and might also be useful for * investigatory purposes. */ #ifdef PG_FORCE_DISABLE_INLINE #undef inline #define inline #endif /* * Attribute macros * * GCC: https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html * GCC: https://gcc.gnu.org/onlinedocs/gcc/Type-Attributes.html * Clang: https://clang.llvm.org/docs/AttributeReference.html * Sunpro: https://docs.oracle.com/cd/E18659_01/html/821-1384/gjzke.html * XLC: https://www.ibm.com/support/knowledgecenter/SSGH2K_13.1.2/com.ibm.xlc131.aix.doc/language_ref/function_attributes.html * XLC: https://www.ibm.com/support/knowledgecenter/SSGH2K_13.1.2/com.ibm.xlc131.aix.doc/language_ref/type_attrib.html */ /* * For compilers which don't support __has_attribute, we just define * __has_attribute(x) to 0 so that we can define macros for various * __attribute__s more easily below. */ #ifndef __has_attribute #define __has_attribute(attribute) 0 #endif /* only GCC supports the unused attribute */ #ifdef __GNUC__ #define pg_attribute_unused() __attribute__((unused)) #else #define pg_attribute_unused() #endif /* * pg_nodiscard means the compiler should warn if the result of a function * call is ignored. The name "nodiscard" is chosen in alignment with * (possibly future) C and C++ standards. For maximum compatibility, use it * as a function declaration specifier, so it goes before the return type. */ #ifdef __GNUC__ #define pg_nodiscard __attribute__((warn_unused_result)) #else #define pg_nodiscard #endif /* * Place this macro before functions that should be allowed to make misaligned * accesses. Think twice before using it on non-x86-specific code! * Testing can be done with "-fsanitize=alignment -fsanitize-trap=alignment" * on clang, or "-fsanitize=alignment -fno-sanitize-recover=alignment" on gcc. */ #if __clang_major__ >= 7 || __GNUC__ >= 8 #define pg_attribute_no_sanitize_alignment() __attribute__((no_sanitize("alignment"))) #else #define pg_attribute_no_sanitize_alignment() #endif /* * pg_attribute_nonnull means the compiler should warn if the function is * called with the listed arguments set to NULL. If no arguments are * listed, the compiler should warn if any pointer arguments are set to NULL. */ #if __has_attribute (nonnull) #define pg_attribute_nonnull(...) __attribute__((nonnull(__VA_ARGS__))) #else #define pg_attribute_nonnull(...) #endif /* * Append PG_USED_FOR_ASSERTS_ONLY to definitions of variables that are only * used in assert-enabled builds, to avoid compiler warnings about unused * variables in assert-disabled builds. */ #ifdef USE_ASSERT_CHECKING #define PG_USED_FOR_ASSERTS_ONLY #else #define PG_USED_FOR_ASSERTS_ONLY pg_attribute_unused() #endif /* GCC and XLC support format attributes */ #if defined(__GNUC__) || defined(__IBMC__) #define pg_attribute_format_arg(a) __attribute__((format_arg(a))) #define pg_attribute_printf(f,a) __attribute__((format(PG_PRINTF_ATTRIBUTE, f, a))) #else #define pg_attribute_format_arg(a) #define pg_attribute_printf(f,a) #endif /* GCC, Sunpro and XLC support aligned, packed and noreturn */ #if defined(__GNUC__) || defined(__SUNPRO_C) || defined(__IBMC__) #define pg_attribute_aligned(a) __attribute__((aligned(a))) #define pg_attribute_noreturn() __attribute__((noreturn)) #define pg_attribute_packed() __attribute__((packed)) #define HAVE_PG_ATTRIBUTE_NORETURN 1 #elif defined(_MSC_VER) /* * MSVC supports aligned. noreturn is also possible but in MSVC it is * declared before the definition while pg_attribute_noreturn() macro * is currently used after the definition. * * Packing is also possible but only by wrapping the entire struct definition * which doesn't fit into our current macro declarations. */ #define pg_attribute_aligned(a) __declspec(align(a)) #define pg_attribute_noreturn() #else /* * NB: aligned and packed are not given default definitions because they * affect code functionality; they *must* be implemented by the compiler * if they are to be used. */ #define pg_attribute_noreturn() #endif /* * Use "pg_attribute_always_inline" in place of "inline" for functions that * we wish to force inlining of, even when the compiler's heuristics would * choose not to. But, if possible, don't force inlining in unoptimized * debug builds. */ #if (defined(__GNUC__) && __GNUC__ > 3 && defined(__OPTIMIZE__)) || defined(__SUNPRO_C) || defined(__IBMC__) /* GCC > 3, Sunpro and XLC support always_inline via __attribute__ */ #define pg_attribute_always_inline __attribute__((always_inline)) inline #elif defined(_MSC_VER) /* MSVC has a special keyword for this */ #define pg_attribute_always_inline __forceinline #else /* Otherwise, the best we can do is to say "inline" */ #define pg_attribute_always_inline inline #endif /* * Forcing a function not to be inlined can be useful if it's the slow path of * a performance-critical function, or should be visible in profiles to allow * for proper cost attribution. Note that unlike the pg_attribute_XXX macros * above, this should be placed before the function's return type and name. */ /* GCC, Sunpro and XLC support noinline via __attribute__ */ #if (defined(__GNUC__) && __GNUC__ > 2) || defined(__SUNPRO_C) || defined(__IBMC__) #define pg_noinline __attribute__((noinline)) /* msvc via declspec */ #elif defined(_MSC_VER) #define pg_noinline __declspec(noinline) #else #define pg_noinline #endif /* * For now, just define pg_attribute_cold and pg_attribute_hot to be empty * macros on minGW 8.1. There appears to be a compiler bug that results in * compilation failure. At this time, we still have at least one buildfarm * animal running that compiler, so this should make that green again. It's * likely this compiler is not popular enough to warrant keeping this code * around forever, so let's just remove it once the last buildfarm animal * upgrades. */ #if defined(__MINGW64__) && __GNUC__ == 8 && __GNUC_MINOR__ == 1 #define pg_attribute_cold #define pg_attribute_hot #else /* * Marking certain functions as "hot" or "cold" can be useful to assist the * compiler in arranging the assembly code in a more efficient way. */ #if __has_attribute (cold) #define pg_attribute_cold __attribute__((cold)) #else #define pg_attribute_cold #endif #if __has_attribute (hot) #define pg_attribute_hot __attribute__((hot)) #else #define pg_attribute_hot #endif #endif /* defined(__MINGW64__) && __GNUC__ == 8 && * __GNUC_MINOR__ == 1 */ /* * Mark a point as unreachable in a portable fashion. This should preferably * be something that the compiler understands, to aid code generation. * In assert-enabled builds, we prefer abort() for debugging reasons. */ #if defined(HAVE__BUILTIN_UNREACHABLE) && !defined(USE_ASSERT_CHECKING) #define pg_unreachable() __builtin_unreachable() #elif defined(_MSC_VER) && !defined(USE_ASSERT_CHECKING) #define pg_unreachable() __assume(0) #else #define pg_unreachable() abort() #endif /* * Hints to the compiler about the likelihood of a branch. Both likely() and * unlikely() return the boolean value of the contained expression. * * These should only be used sparingly, in very hot code paths. It's very easy * to mis-estimate likelihoods. */ #if __GNUC__ >= 3 #define likely(x) __builtin_expect((x) != 0, 1) #define unlikely(x) __builtin_expect((x) != 0, 0) #else #define likely(x) ((x) != 0) #define unlikely(x) ((x) != 0) #endif /* * CppAsString * Convert the argument to a string, using the C preprocessor. * CppAsString2 * Convert the argument to a string, after one round of macro expansion. * CppConcat * Concatenate two arguments together, using the C preprocessor. * * Note: There used to be support here for pre-ANSI C compilers that didn't * support # and ##. Nowadays, these macros are just for clarity and/or * backward compatibility with existing PostgreSQL code. */ #define CppAsString(identifier) #identifier #define CppAsString2(x) CppAsString(x) #define CppConcat(x, y) x##y /* * VA_ARGS_NARGS * Returns the number of macro arguments it is passed. * * An empty argument still counts as an argument, so effectively, this is * "one more than the number of commas in the argument list". * * This works for up to 63 arguments. Internally, VA_ARGS_NARGS_() is passed * 64+N arguments, and the C99 standard only requires macros to allow up to * 127 arguments, so we can't portably go higher. The implementation is * pretty trivial: VA_ARGS_NARGS_() returns its 64th argument, and we set up * the call so that that is the appropriate one of the list of constants. * This idea is due to Laurent Deniau. * * MSVC has an implementation of __VA_ARGS__ that doesn't conform to the * standard unless you use the /Zc:preprocessor compiler flag, but that * isn't available before Visual Studio 2019. For now, use a different * definition that also works on older compilers. */ #ifdef _MSC_VER #define EXPAND(args) args #define VA_ARGS_NARGS(...) \ VA_ARGS_NARGS_ EXPAND((__VA_ARGS__, \ 63,62,61,60, \ 59,58,57,56,55,54,53,52,51,50, \ 49,48,47,46,45,44,43,42,41,40, \ 39,38,37,36,35,34,33,32,31,30, \ 29,28,27,26,25,24,23,22,21,20, \ 19,18,17,16,15,14,13,12,11,10, \ 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)) #else #define VA_ARGS_NARGS(...) \ VA_ARGS_NARGS_(__VA_ARGS__, \ 63,62,61,60, \ 59,58,57,56,55,54,53,52,51,50, \ 49,48,47,46,45,44,43,42,41,40, \ 39,38,37,36,35,34,33,32,31,30, \ 29,28,27,26,25,24,23,22,21,20, \ 19,18,17,16,15,14,13,12,11,10, \ 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) #endif #define VA_ARGS_NARGS_( \ _01,_02,_03,_04,_05,_06,_07,_08,_09,_10, \ _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \ _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \ _31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \ _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \ _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \ _61,_62,_63, N, ...) \ (N) /* * Generic function pointer. This can be used in the rare cases where it's * necessary to cast a function pointer to a seemingly incompatible function * pointer type while avoiding gcc's -Wcast-function-type warnings. */ typedef void (*pg_funcptr_t) (void); /* * We require C99, hence the compiler should understand flexible array * members. However, for documentation purposes we still consider it to be * project style to write "field[FLEXIBLE_ARRAY_MEMBER]" not just "field[]". * When computing the size of such an object, use "offsetof(struct s, f)" * for portability. Don't use "offsetof(struct s, f[0])", as this doesn't * work with MSVC and with C++ compilers. */ #define FLEXIBLE_ARRAY_MEMBER /* empty */ /* * Does the compiler support #pragma GCC system_header? We optionally use it * to avoid warnings that we can't fix (e.g. in the perl headers). * See https://gcc.gnu.org/onlinedocs/cpp/System-Headers.html * * Headers for which we do not want to show compiler warnings can, * conditionally, use #pragma GCC system_header to avoid warnings. Obviously * this should only be used for external headers over which we do not have * control. * * Support for the pragma is tested here, instead of during configure, as gcc * also warns about the pragma being used in a .c file. It's surprisingly hard * to get autoconf to use .h as the file-ending. Looks like gcc has * implemented the pragma since the 2000, so this test should suffice. * * * Alternatively, we could add the include paths for problematic headers with * -isystem, but that is a larger hammer and is harder to search for. * * A more granular alternative would be to use #pragma GCC diagnostic * push/ignored/pop, but gcc warns about unknown warnings being ignored, so * every to-be-ignored-temporarily compiler warning would require its own * pg_config.h symbol and #ifdef. */ #ifdef __GNUC__ #define HAVE_PRAGMA_GCC_SYSTEM_HEADER 1 #endif /* ---------------------------------------------------------------- * Section 2: bool, true, false * ---------------------------------------------------------------- */ /* * bool * Boolean value, either true or false. * * We use stdbool.h if available and its bool has size 1. That's useful for * better compiler and debugger output and for compatibility with third-party * libraries. But PostgreSQL currently cannot deal with bool of other sizes; * there are static assertions around the code to prevent that. * * For C++ compilers, we assume the compiler has a compatible built-in * definition of bool. * * See also the version of this code in src/interfaces/ecpg/include/ecpglib.h. */ #ifndef __cplusplus #ifdef PG_USE_STDBOOL #include <stdbool.h> #else #ifndef bool typedef unsigned char bool; #endif #ifndef true #define true ((bool) 1) #endif #ifndef false #define false ((bool) 0) #endif #endif /* not PG_USE_STDBOOL */ #endif /* not C++ */ /* ---------------------------------------------------------------- * Section 3: standard system types * ---------------------------------------------------------------- */ /* * Pointer * Variable holding address of any memory resident object. * * XXX Pointer arithmetic is done with this, so it can't be void * * under "true" ANSI compilers. */ typedef char *Pointer; /* * intN * Signed integer, EXACTLY N BITS IN SIZE, * used for numerical computations and the * frontend/backend protocol. */ #ifndef HAVE_INT8 typedef signed char int8; /* == 8 bits */ typedef signed short int16; /* == 16 bits */ typedef signed int int32; /* == 32 bits */ #endif /* not HAVE_INT8 */ /* * uintN * Unsigned integer, EXACTLY N BITS IN SIZE, * used for numerical computations and the * frontend/backend protocol. */ #ifndef HAVE_UINT8 typedef unsigned char uint8; /* == 8 bits */ typedef unsigned short uint16; /* == 16 bits */ typedef unsigned int uint32; /* == 32 bits */ #endif /* not HAVE_UINT8 */ /* * bitsN * Unit of bitwise operation, AT LEAST N BITS IN SIZE. */ typedef uint8 bits8; /* >= 8 bits */ typedef uint16 bits16; /* >= 16 bits */ typedef uint32 bits32; /* >= 32 bits */ /* * 64-bit integers */ typedef long long int int64; typedef unsigned long long int uint64; #define INT64CONST(x) (x##LL) #define UINT64CONST(x) (x##ULL) /* snprintf format strings to use for 64-bit integers */ #define INT64_FORMAT "%" INT64_MODIFIER "d" #define UINT64_FORMAT "%" INT64_MODIFIER "u" /* * 128-bit signed and unsigned integers * There currently is only limited support for such types. * E.g. 128bit literals and snprintf are not supported; but math is. * Also, because we exclude such types when choosing MAXIMUM_ALIGNOF, * it must be possible to coerce the compiler to allocate them on no * more than MAXALIGN boundaries. */ #if defined(PG_INT128_TYPE) #if defined(pg_attribute_aligned) || ALIGNOF_PG_INT128_TYPE <= MAXIMUM_ALIGNOF #define HAVE_INT128 1 typedef PG_INT128_TYPE int128 #if defined(pg_attribute_aligned) pg_attribute_aligned(MAXIMUM_ALIGNOF) #endif ; typedef unsigned PG_INT128_TYPE uint128 #if defined(pg_attribute_aligned) pg_attribute_aligned(MAXIMUM_ALIGNOF) #endif ; #endif #endif /* * stdint.h limits aren't guaranteed to have compatible types with our fixed * width types. So just define our own. */ #define PG_INT8_MIN (-0x7F-1) #define PG_INT8_MAX (0x7F) #define PG_UINT8_MAX (0xFF) #define PG_INT16_MIN (-0x7FFF-1) #define PG_INT16_MAX (0x7FFF) #define PG_UINT16_MAX (0xFFFF) #define PG_INT32_MIN (-0x7FFFFFFF-1) #define PG_INT32_MAX (0x7FFFFFFF) #define PG_UINT32_MAX (0xFFFFFFFFU) #define PG_INT64_MIN (-INT64CONST(0x7FFFFFFFFFFFFFFF) - 1) #define PG_INT64_MAX INT64CONST(0x7FFFFFFFFFFFFFFF) #define PG_UINT64_MAX UINT64CONST(0xFFFFFFFFFFFFFFFF) /* * We now always use int64 timestamps, but keep this symbol defined for the * benefit of external code that might test it. */ #define HAVE_INT64_TIMESTAMP /* * Size * Size of any memory resident object, as returned by sizeof. */ typedef size_t Size; /* * Index * Index into any memory resident array. * * Note: * Indices are non negative. */ typedef unsigned int Index; /* * Offset * Offset into any memory resident array. * * Note: * This differs from an Index in that an Index is always * non negative, whereas Offset may be negative. */ typedef signed int Offset; /* * Common Postgres datatype names (as used in the catalogs) */ typedef float float4; typedef double float8; #ifdef USE_FLOAT8_BYVAL #define FLOAT8PASSBYVAL true #else #define FLOAT8PASSBYVAL false #endif /* * Oid, RegProcedure, TransactionId, SubTransactionId, MultiXactId, * CommandId */ /* typedef Oid is in postgres_ext.h */ /* * regproc is the type name used in the include/catalog headers, but * RegProcedure is the preferred name in C code. */ typedef Oid regproc; typedef regproc RegProcedure; typedef uint32 TransactionId; typedef uint32 LocalTransactionId; typedef uint32 SubTransactionId; #define InvalidSubTransactionId ((SubTransactionId) 0) #define TopSubTransactionId ((SubTransactionId) 1) /* MultiXactId must be equivalent to TransactionId, to fit in t_xmax */ typedef TransactionId MultiXactId; typedef uint32 MultiXactOffset; typedef uint32 CommandId; #define FirstCommandId ((CommandId) 0) #define InvalidCommandId (~(CommandId)0) /* ---------------- * Variable-length datatypes all share the 'struct varlena' header. * * NOTE: for TOASTable types, this is an oversimplification, since the value * may be compressed or moved out-of-line. However datatype-specific routines * are mostly content to deal with de-TOASTed values only, and of course * client-side routines should never see a TOASTed value. But even in a * de-TOASTed value, beware of touching vl_len_ directly, as its * representation is no longer convenient. It's recommended that code always * use macros VARDATA_ANY, VARSIZE_ANY, VARSIZE_ANY_EXHDR, VARDATA, VARSIZE, * and SET_VARSIZE instead of relying on direct mentions of the struct fields. * See postgres.h for details of the TOASTed form. * ---------------- */ struct varlena { char vl_len_[4]; /* Do not touch this field directly! */ char vl_dat[FLEXIBLE_ARRAY_MEMBER]; /* Data content is here */ }; #define VARHDRSZ ((int32) sizeof(int32)) /* * These widely-used datatypes are just a varlena header and the data bytes. * There is no terminating null or anything like that --- the data length is * always VARSIZE_ANY_EXHDR(ptr). */ typedef struct varlena bytea; typedef struct varlena text; typedef struct varlena BpChar; /* blank-padded char, ie SQL char(n) */ typedef struct varlena VarChar; /* var-length char, ie SQL varchar(n) */ /* * Specialized array types. These are physically laid out just the same * as regular arrays (so that the regular array subscripting code works * with them). They exist as distinct types mostly for historical reasons: * they have nonstandard I/O behavior which we don't want to change for fear * of breaking applications that look at the system catalogs. There is also * an implementation issue for oidvector: it's part of the primary key for * pg_proc, and we can't use the normal btree array support routines for that * without circularity. */ typedef struct { int32 vl_len_; /* these fields must match ArrayType! */ int ndim; /* always 1 for int2vector */ int32 dataoffset; /* always 0 for int2vector */ Oid elemtype; int dim1; int lbound1; int16 values[FLEXIBLE_ARRAY_MEMBER]; } int2vector; typedef struct { int32 vl_len_; /* these fields must match ArrayType! */ int ndim; /* always 1 for oidvector */ int32 dataoffset; /* always 0 for oidvector */ Oid elemtype; int dim1; int lbound1; Oid values[FLEXIBLE_ARRAY_MEMBER]; } oidvector; #define NameStr(name) ((name).data) /* ---------------------------------------------------------------- * Section 4: IsValid macros for system types * ---------------------------------------------------------------- */ /* * BoolIsValid * True iff bool is valid. */ #define BoolIsValid(boolean) ((boolean) == false || (boolean) == true) /* * PointerIsValid * True iff pointer is valid. */ #define PointerIsValid(pointer) ((const void*)(pointer) != NULL) /* * PointerIsAligned * True iff pointer is properly aligned to point to the given type. */ #define PointerIsAligned(pointer, type) \ (((uintptr_t)(pointer) % (sizeof (type))) == 0) #define OffsetToPointer(base, offset) \ ((void *)((char *) base + offset)) #define OidIsValid(objectId) ((bool) ((objectId) != InvalidOid)) #define RegProcedureIsValid(p) OidIsValid(p) /* ---------------------------------------------------------------- * Section 5: lengthof, alignment * ---------------------------------------------------------------- */ /* * lengthof * Number of elements in an array. */ #define lengthof(array) (sizeof (array) / sizeof ((array)[0])) /* ---------------- * Alignment macros: align a length or address appropriately for a given type. * The fooALIGN() macros round up to a multiple of the required alignment, * while the fooALIGN_DOWN() macros round down. The latter are more useful * for problems like "how many X-sized structures will fit in a page?". * * NOTE: TYPEALIGN[_DOWN] will not work if ALIGNVAL is not a power of 2. * That case seems extremely unlikely to be needed in practice, however. * * NOTE: MAXIMUM_ALIGNOF, and hence MAXALIGN(), intentionally exclude any * larger-than-8-byte types the compiler might have. * ---------------- */ #define TYPEALIGN(ALIGNVAL,LEN) \ (((uintptr_t) (LEN) + ((ALIGNVAL) - 1)) & ~((uintptr_t) ((ALIGNVAL) - 1))) #define SHORTALIGN(LEN) TYPEALIGN(ALIGNOF_SHORT, (LEN)) #define INTALIGN(LEN) TYPEALIGN(ALIGNOF_INT, (LEN)) #define LONGALIGN(LEN) TYPEALIGN(ALIGNOF_LONG, (LEN)) #define DOUBLEALIGN(LEN) TYPEALIGN(ALIGNOF_DOUBLE, (LEN)) #define MAXALIGN(LEN) TYPEALIGN(MAXIMUM_ALIGNOF, (LEN)) /* MAXALIGN covers only built-in types, not buffers */ #define BUFFERALIGN(LEN) TYPEALIGN(ALIGNOF_BUFFER, (LEN)) #define CACHELINEALIGN(LEN) TYPEALIGN(PG_CACHE_LINE_SIZE, (LEN)) #define TYPEALIGN_DOWN(ALIGNVAL,LEN) \ (((uintptr_t) (LEN)) & ~((uintptr_t) ((ALIGNVAL) - 1))) #define SHORTALIGN_DOWN(LEN) TYPEALIGN_DOWN(ALIGNOF_SHORT, (LEN)) #define INTALIGN_DOWN(LEN) TYPEALIGN_DOWN(ALIGNOF_INT, (LEN)) #define LONGALIGN_DOWN(LEN) TYPEALIGN_DOWN(ALIGNOF_LONG, (LEN)) #define DOUBLEALIGN_DOWN(LEN) TYPEALIGN_DOWN(ALIGNOF_DOUBLE, (LEN)) #define MAXALIGN_DOWN(LEN) TYPEALIGN_DOWN(MAXIMUM_ALIGNOF, (LEN)) #define BUFFERALIGN_DOWN(LEN) TYPEALIGN_DOWN(ALIGNOF_BUFFER, (LEN)) /* * The above macros will not work with types wider than uintptr_t, like with * uint64 on 32-bit platforms. That's not problem for the usual use where a * pointer or a length is aligned, but for the odd case that you need to * align something (potentially) wider, use TYPEALIGN64. */ #define TYPEALIGN64(ALIGNVAL,LEN) \ (((uint64) (LEN) + ((ALIGNVAL) - 1)) & ~((uint64) ((ALIGNVAL) - 1))) /* we don't currently need wider versions of the other ALIGN macros */ #define MAXALIGN64(LEN) TYPEALIGN64(MAXIMUM_ALIGNOF, (LEN)) /* ---------------------------------------------------------------- * Section 6: assertions * ---------------------------------------------------------------- */ /* * USE_ASSERT_CHECKING, if defined, turns on all the assertions. * - plai 9/5/90 * * It should _NOT_ be defined in releases or in benchmark copies */ /* * Assert() can be used in both frontend and backend code. In frontend code it * just calls the standard assert, if it's available. If use of assertions is * not configured, it does nothing. */ #ifndef USE_ASSERT_CHECKING #define Assert(condition) ((void)true) #define AssertMacro(condition) ((void)true) #elif defined(FRONTEND) #include <assert.h> #define Assert(p) assert(p) #define AssertMacro(p) ((void) assert(p)) #else /* USE_ASSERT_CHECKING && !FRONTEND */ /* * Assert * Generates a fatal exception if the given condition is false. */ #define Assert(condition) \ do { \ if (!(condition)) \ ExceptionalCondition(#condition, __FILE__, __LINE__); \ } while (0) /* * AssertMacro is the same as Assert but it's suitable for use in * expression-like macros, for example: * * #define foo(x) (AssertMacro(x != 0), bar(x)) */ #define AssertMacro(condition) \ ((void) ((condition) || \ (ExceptionalCondition(#condition, __FILE__, __LINE__), 0))) #endif /* USE_ASSERT_CHECKING && !FRONTEND */ /* * Check that `ptr' is `bndr' aligned. */ #define AssertPointerAlignment(ptr, bndr) \ Assert(TYPEALIGN(bndr, (uintptr_t)(ptr)) == (uintptr_t)(ptr)) /* * ExceptionalCondition is compiled into the backend whether or not * USE_ASSERT_CHECKING is defined, so as to support use of extensions * that are built with that #define with a backend that isn't. Hence, * we should declare it as long as !FRONTEND. */ #ifndef FRONTEND extern void ExceptionalCondition(const char *conditionName, const char *fileName, int lineNumber) pg_attribute_noreturn(); #endif /* * Macros to support compile-time assertion checks. * * If the "condition" (a compile-time-constant expression) evaluates to false, * throw a compile error using the "errmessage" (a string literal). * * C11 has _Static_assert(), and most C99 compilers already support that. For * portability, we wrap it into StaticAssertDecl(). _Static_assert() is a * "declaration", and so it must be placed where for example a variable * declaration would be valid. As long as we compile with * -Wno-declaration-after-statement, that also means it cannot be placed after * statements in a function. Macros StaticAssertStmt() and StaticAssertExpr() * make it safe to use as a statement or in an expression, respectively. * * For compilers without _Static_assert(), we fall back on a kluge that * assumes the compiler will complain about a negative width for a struct * bit-field. This will not include a helpful error message, but it beats not * getting an error at all. */ #ifndef __cplusplus #ifdef HAVE__STATIC_ASSERT #define StaticAssertDecl(condition, errmessage) \ _Static_assert(condition, errmessage) #define StaticAssertStmt(condition, errmessage) \ do { _Static_assert(condition, errmessage); } while(0) #define StaticAssertExpr(condition, errmessage) \ ((void) ({ StaticAssertStmt(condition, errmessage); true; })) #else /* !HAVE__STATIC_ASSERT */ #define StaticAssertDecl(condition, errmessage) \ extern void static_assert_func(int static_assert_failure[(condition) ? 1 : -1]) #define StaticAssertStmt(condition, errmessage) \ ((void) sizeof(struct { int static_assert_failure : (condition) ? 1 : -1; })) #define StaticAssertExpr(condition, errmessage) \ StaticAssertStmt(condition, errmessage) #endif /* HAVE__STATIC_ASSERT */ #else /* C++ */ #if defined(__cpp_static_assert) && __cpp_static_assert >= 200410 #define StaticAssertDecl(condition, errmessage) \ static_assert(condition, errmessage) #define StaticAssertStmt(condition, errmessage) \ static_assert(condition, errmessage) #define StaticAssertExpr(condition, errmessage) \ ({ static_assert(condition, errmessage); }) #else /* !__cpp_static_assert */ #define StaticAssertDecl(condition, errmessage) \ extern void static_assert_func(int static_assert_failure[(condition) ? 1 : -1]) #define StaticAssertStmt(condition, errmessage) \ do { struct static_assert_struct { int static_assert_failure : (condition) ? 1 : -1; }; } while(0) #define StaticAssertExpr(condition, errmessage) \ ((void) ({ StaticAssertStmt(condition, errmessage); })) #endif /* __cpp_static_assert */ #endif /* C++ */ /* * Compile-time checks that a variable (or expression) has the specified type. * * AssertVariableIsOfType() can be used as a statement. * AssertVariableIsOfTypeMacro() is intended for use in macros, eg * #define foo(x) (AssertVariableIsOfTypeMacro(x, int), bar(x)) * * If we don't have __builtin_types_compatible_p, we can still assert that * the types have the same size. This is far from ideal (especially on 32-bit * platforms) but it provides at least some coverage. */ #ifdef HAVE__BUILTIN_TYPES_COMPATIBLE_P #define AssertVariableIsOfType(varname, typename) \ StaticAssertStmt(__builtin_types_compatible_p(__typeof__(varname), typename), \ CppAsString(varname) " does not have type " CppAsString(typename)) #define AssertVariableIsOfTypeMacro(varname, typename) \ (StaticAssertExpr(__builtin_types_compatible_p(__typeof__(varname), typename), \ CppAsString(varname) " does not have type " CppAsString(typename))) #else /* !HAVE__BUILTIN_TYPES_COMPATIBLE_P */ #define AssertVariableIsOfType(varname, typename) \ StaticAssertStmt(sizeof(varname) == sizeof(typename), \ CppAsString(varname) " does not have type " CppAsString(typename)) #define AssertVariableIsOfTypeMacro(varname, typename) \ (StaticAssertExpr(sizeof(varname) == sizeof(typename), \ CppAsString(varname) " does not have type " CppAsString(typename))) #endif /* HAVE__BUILTIN_TYPES_COMPATIBLE_P */ /* ---------------------------------------------------------------- * Section 7: widely useful macros * ---------------------------------------------------------------- */ /* * Max * Return the maximum of two numbers. */ #define Max(x, y) ((x) > (y) ? (x) : (y)) /* * Min * Return the minimum of two numbers. */ #define Min(x, y) ((x) < (y) ? (x) : (y)) /* Get a bit mask of the bits set in non-long aligned addresses */ #define LONG_ALIGN_MASK (sizeof(long) - 1) /* * MemSet * Exactly the same as standard library function memset(), but considerably * faster for zeroing small word-aligned structures (such as parsetree nodes). * This has to be a macro because the main point is to avoid function-call * overhead. However, we have also found that the loop is faster than * native libc memset() on some platforms, even those with assembler * memset() functions. More research needs to be done, perhaps with * MEMSET_LOOP_LIMIT tests in configure. */ #define MemSet(start, val, len) \ do \ { \ /* must be void* because we don't know if it is integer aligned yet */ \ void *_vstart = (void *) (start); \ int _val = (val); \ Size _len = (len); \ \ if ((((uintptr_t) _vstart) & LONG_ALIGN_MASK) == 0 && \ (_len & LONG_ALIGN_MASK) == 0 && \ _val == 0 && \ _len <= MEMSET_LOOP_LIMIT && \ /* \ * If MEMSET_LOOP_LIMIT == 0, optimizer should find \ * the whole "if" false at compile time. \ */ \ MEMSET_LOOP_LIMIT != 0) \ { \ long *_start = (long *) _vstart; \ long *_stop = (long *) ((char *) _start + _len); \ while (_start < _stop) \ *_start++ = 0; \ } \ else \ memset(_vstart, _val, _len); \ } while (0) /* * MemSetAligned is the same as MemSet except it omits the test to see if * "start" is word-aligned. This is okay to use if the caller knows a-priori * that the pointer is suitably aligned (typically, because he just got it * from palloc(), which always delivers a max-aligned pointer). */ #define MemSetAligned(start, val, len) \ do \ { \ long *_start = (long *) (start); \ int _val = (val); \ Size _len = (len); \ \ if ((_len & LONG_ALIGN_MASK) == 0 && \ _val == 0 && \ _len <= MEMSET_LOOP_LIMIT && \ MEMSET_LOOP_LIMIT != 0) \ { \ long *_stop = (long *) ((char *) _start + _len); \ while (_start < _stop) \ *_start++ = 0; \ } \ else \ memset(_start, _val, _len); \ } while (0) /* * MemSetTest/MemSetLoop are a variant version that allow all the tests in * MemSet to be done at compile time in cases where "val" and "len" are * constants *and* we know the "start" pointer must be word-aligned. * If MemSetTest succeeds, then it is okay to use MemSetLoop, otherwise use * MemSetAligned. Beware of multiple evaluations of the arguments when using * this approach. */ #define MemSetTest(val, len) \ ( ((len) & LONG_ALIGN_MASK) == 0 && \ (len) <= MEMSET_LOOP_LIMIT && \ MEMSET_LOOP_LIMIT != 0 && \ (val) == 0 ) #define MemSetLoop(start, val, len) \ do \ { \ long * _start = (long *) (start); \ long * _stop = (long *) ((char *) _start + (Size) (len)); \ \ while (_start < _stop) \ *_start++ = 0; \ } while (0) /* * Macros for range-checking float values before converting to integer. * We must be careful here that the boundary values are expressed exactly * in the float domain. PG_INTnn_MIN is an exact power of 2, so it will * be represented exactly; but PG_INTnn_MAX isn't, and might get rounded * off, so avoid using that. * The input must be rounded to an integer beforehand, typically with rint(), * else we might draw the wrong conclusion about close-to-the-limit values. * These macros will do the right thing for Inf, but not necessarily for NaN, * so check isnan(num) first if that's a possibility. */ #define FLOAT4_FITS_IN_INT16(num) \ ((num) >= (float4) PG_INT16_MIN && (num) < -((float4) PG_INT16_MIN)) #define FLOAT4_FITS_IN_INT32(num) \ ((num) >= (float4) PG_INT32_MIN && (num) < -((float4) PG_INT32_MIN)) #define FLOAT4_FITS_IN_INT64(num) \ ((num) >= (float4) PG_INT64_MIN && (num) < -((float4) PG_INT64_MIN)) #define FLOAT8_FITS_IN_INT16(num) \ ((num) >= (float8) PG_INT16_MIN && (num) < -((float8) PG_INT16_MIN)) #define FLOAT8_FITS_IN_INT32(num) \ ((num) >= (float8) PG_INT32_MIN && (num) < -((float8) PG_INT32_MIN)) #define FLOAT8_FITS_IN_INT64(num) \ ((num) >= (float8) PG_INT64_MIN && (num) < -((float8) PG_INT64_MIN)) /* ---------------------------------------------------------------- * Section 8: random stuff * ---------------------------------------------------------------- */ /* * Invert the sign of a qsort-style comparison result, ie, exchange negative * and positive integer values, being careful not to get the wrong answer * for INT_MIN. The argument should be an integral variable. */ #define INVERT_COMPARE_RESULT(var) \ ((var) = ((var) < 0) ? 1 : -(var)) /* msb for char */ #define HIGHBIT (0x80) #define IS_HIGHBIT_SET(ch) ((unsigned char)(ch) & HIGHBIT) /* * Support macros for escaping strings. escape_backslash should be true * if generating a non-standard-conforming string. Prefixing a string * with ESCAPE_STRING_SYNTAX guarantees it is non-standard-conforming. * Beware of multiple evaluation of the "ch" argument! */ #define SQL_STR_DOUBLE(ch, escape_backslash) \ ((ch) == '\'' || ((ch) == '\\' && (escape_backslash))) #define ESCAPE_STRING_SYNTAX 'E' #define STATUS_OK (0) #define STATUS_ERROR (-1) #define STATUS_EOF (-2) /* * gettext support */ #ifndef ENABLE_NLS /* stuff we'd otherwise get from <libintl.h> */ #define gettext(x) (x) #define dgettext(d,x) (x) #define ngettext(s,p,n) ((n) == 1 ? (s) : (p)) #define dngettext(d,s,p,n) ((n) == 1 ? (s) : (p)) #endif #define _(x) gettext(x) /* * Use this to mark string constants as needing translation at some later * time, rather than immediately. This is useful for cases where you need * access to the original string and translated string, and for cases where * immediate translation is not possible, like when initializing global * variables. * * https://www.gnu.org/software/gettext/manual/html_node/Special-cases.html */ #define gettext_noop(x) (x) /* * To better support parallel installations of major PostgreSQL * versions as well as parallel installations of major library soname * versions, we mangle the gettext domain name by appending those * version numbers. The coding rule ought to be that wherever the * domain name is mentioned as a literal, it must be wrapped into * PG_TEXTDOMAIN(). The macros below do not work on non-literals; but * that is somewhat intentional because it avoids having to worry * about multiple states of premangling and postmangling as the values * are being passed around. * * Make sure this matches the installation rules in nls-global.mk. */ #ifdef SO_MAJOR_VERSION #define PG_TEXTDOMAIN(domain) (domain CppAsString2(SO_MAJOR_VERSION) "-" PG_MAJORVERSION) #else #define PG_TEXTDOMAIN(domain) (domain "-" PG_MAJORVERSION) #endif /* * Macro that allows to cast constness and volatile away from an expression, but doesn't * allow changing the underlying type. Enforcement of the latter * currently only works for gcc like compilers. * * Please note IT IS NOT SAFE to cast constness away if the result will ever * be modified (it would be undefined behaviour). Doing so anyway can cause * compiler misoptimizations or runtime crashes (modifying readonly memory). * It is only safe to use when the result will not be modified, but API * design or language restrictions prevent you from declaring that * (e.g. because a function returns both const and non-const variables). * * Note that this only works in function scope, not for global variables (it'd * be nice, but not trivial, to improve that). */ #if defined(__cplusplus) #define unconstify(underlying_type, expr) const_cast<underlying_type>(expr) #define unvolatize(underlying_type, expr) const_cast<underlying_type>(expr) #elif defined(HAVE__BUILTIN_TYPES_COMPATIBLE_P) #define unconstify(underlying_type, expr) \ (StaticAssertExpr(__builtin_types_compatible_p(__typeof(expr), const underlying_type), \ "wrong cast"), \ (underlying_type) (expr)) #define unvolatize(underlying_type, expr) \ (StaticAssertExpr(__builtin_types_compatible_p(__typeof(expr), volatile underlying_type), \ "wrong cast"), \ (underlying_type) (expr)) #else #define unconstify(underlying_type, expr) \ ((underlying_type) (expr)) #define unvolatize(underlying_type, expr) \ ((underlying_type) (expr)) #endif /* ---------------------------------------------------------------- * Section 9: system-specific hacks * * This should be limited to things that absolutely have to be * included in every source file. The port-specific header file * is usually a better place for this sort of thing. * ---------------------------------------------------------------- */ /* * NOTE: this is also used for opening text files. * WIN32 treats Control-Z as EOF in files opened in text mode. * Therefore, we open files in binary mode on Win32 so we can read * literal control-Z. The other affect is that we see CRLF, but * that is OK because we can already handle those cleanly. */ #if defined(WIN32) || defined(__CYGWIN__) #define PG_BINARY O_BINARY #define PG_BINARY_A "ab" #define PG_BINARY_R "rb" #define PG_BINARY_W "wb" #else #define PG_BINARY 0 #define PG_BINARY_A "a" #define PG_BINARY_R "r" #define PG_BINARY_W "w" #endif /* * Provide prototypes for routines not present in a particular machine's * standard C library. */ #if !HAVE_DECL_FDATASYNC extern int fdatasync(int fildes); #endif /* * Thin wrappers that convert strings to exactly 64-bit integers, matching our * definition of int64. (For the naming, compare that POSIX has * strtoimax()/strtoumax() which return intmax_t/uintmax_t.) */ #ifdef HAVE_LONG_INT_64 #define strtoi64(str, endptr, base) ((int64) strtol(str, endptr, base)) #define strtou64(str, endptr, base) ((uint64) strtoul(str, endptr, base)) #else #define strtoi64(str, endptr, base) ((int64) strtoll(str, endptr, base)) #define strtou64(str, endptr, base) ((uint64) strtoull(str, endptr, base)) #endif /* * Similarly, wrappers around labs()/llabs() matching our int64. */ #ifdef HAVE_LONG_INT_64 #define i64abs(i) labs(i) #else #define i64abs(i) llabs(i) #endif /* * Use "extern PGDLLIMPORT ..." to declare variables that are defined * in the core backend and need to be accessible by loadable modules. * No special marking is required on most ports. */ #ifndef PGDLLIMPORT #define PGDLLIMPORT #endif /* * Use "extern PGDLLEXPORT ..." to declare functions that are defined in * loadable modules and need to be callable by the core backend or other * loadable modules. * If the compiler knows __attribute__((visibility("*"))), we use that, * unless we already have a platform-specific definition. Otherwise, * no special marking is required. */ #ifndef PGDLLEXPORT #ifdef HAVE_VISIBILITY_ATTRIBUTE #define PGDLLEXPORT __attribute__((visibility("default"))) #else #define PGDLLEXPORT #endif #endif /* * The following is used as the arg list for signal handlers. Any ports * that take something other than an int argument should override this in * their pg_config_os.h file. Note that variable names are required * because it is used in both the prototypes as well as the definitions. * Note also the long name. We expect that this won't collide with * other names causing compiler warnings. */ #ifndef SIGNAL_ARGS #define SIGNAL_ARGS int postgres_signal_arg #endif /* * When there is no sigsetjmp, its functionality is provided by plain * setjmp. We now support the case only on Windows. However, it seems * that MinGW-64 has some longstanding issues in its setjmp support, * so on that toolchain we cheat and use gcc's builtins. */ #ifdef WIN32 #ifdef __MINGW64__ typedef intptr_t sigjmp_buf[5]; #define sigsetjmp(x,y) __builtin_setjmp(x) #define siglongjmp __builtin_longjmp #else /* !__MINGW64__ */ #define sigjmp_buf jmp_buf #define sigsetjmp(x,y) setjmp(x) #define siglongjmp longjmp #endif /* __MINGW64__ */ #endif /* WIN32 */ /* /port compatibility functions */ #endif /* C_H */ /*------------------------------------------------------------------------- * * pg_list.h * interface for PostgreSQL generic list package * * Once upon a time, parts of Postgres were written in Lisp and used real * cons-cell lists for major data structures. When that code was rewritten * in C, we initially had a faithful emulation of cons-cell lists, which * unsurprisingly was a performance bottleneck. A couple of major rewrites * later, these data structures are actually simple expansible arrays; * but the "List" name and a lot of the notation survives. * * One important concession to the original implementation is that an empty * list is always represented by a null pointer (preferentially written NIL). * Non-empty lists have a header, which will not be relocated as long as the * list remains non-empty, and an expansible data array. * * We support four types of lists: * * T_List: lists of pointers * (in practice usually pointers to Nodes, but not always; * declared as "void *" to minimize casting annoyances) * T_IntList: lists of integers * T_OidList: lists of Oids * T_XidList: lists of TransactionIds * (the XidList infrastructure is less complete than the other cases) * * (At the moment, ints, Oids, and XIDs are the same size, but they may not * always be so; be careful to use the appropriate list type for your data.) * * * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/nodes/pg_list.h * *------------------------------------------------------------------------- */ #ifndef PG_LIST_H #define PG_LIST_H typedef union ListCell { void *ptr_value; int int_value; Oid oid_value; TransactionId xid_value; } ListCell; typedef struct List { NodeTag type; /* T_List, T_IntList, T_OidList, or T_XidList */ int length; /* number of elements currently present */ int max_length; /* allocated length of elements[] */ ListCell *elements; /* re-allocatable array of cells */ /* We may allocate some cells along with the List header: */ ListCell initial_elements[FLEXIBLE_ARRAY_MEMBER]; /* If elements == initial_elements, it's not a separate allocation */ } List; /* * The *only* valid representation of an empty list is NIL; in other * words, a non-NIL list is guaranteed to have length >= 1. */ #define NIL ((List *) NULL) /* * State structs for various looping macros below. */ typedef struct ForEachState { const List *l; /* list we're looping through */ int i; /* current element index */ } ForEachState; typedef struct ForBothState { const List *l1; /* lists we're looping through */ const List *l2; int i; /* common element index */ } ForBothState; typedef struct ForBothCellState { const List *l1; /* lists we're looping through */ const List *l2; int i1; /* current element indexes */ int i2; } ForBothCellState; typedef struct ForThreeState { const List *l1; /* lists we're looping through */ const List *l2; const List *l3; int i; /* common element index */ } ForThreeState; typedef struct ForFourState { const List *l1; /* lists we're looping through */ const List *l2; const List *l3; const List *l4; int i; /* common element index */ } ForFourState; typedef struct ForFiveState { const List *l1; /* lists we're looping through */ const List *l2; const List *l3; const List *l4; const List *l5; int i; /* common element index */ } ForFiveState; /* * These routines are small enough, and used often enough, to justify being * inline. */ /* Fetch address of list's first cell; NULL if empty list */ static inline ListCell * list_head(const List *l) { return l ? &l->elements[0] : NULL; } /* Fetch address of list's last cell; NULL if empty list */ static inline ListCell * list_tail(const List *l) { return l ? &l->elements[l->length - 1] : NULL; } /* Fetch address of list's second cell, if it has one, else NULL */ static inline ListCell * list_second_cell(const List *l) { if (l && l->length >= 2) return &l->elements[1]; else return NULL; } /* Fetch list's length */ static inline int list_length(const List *l) { return l ? l->length : 0; } /* * Macros to access the data values within List cells. * * Note that with the exception of the "xxx_node" macros, these are * lvalues and can be assigned to. * * NB: There is an unfortunate legacy from a previous incarnation of * the List API: the macro lfirst() was used to mean "the data in this * cons cell". To avoid changing every usage of lfirst(), that meaning * has been kept. As a result, lfirst() takes a ListCell and returns * the data it contains; to get the data in the first cell of a * List, use linitial(). Worse, lsecond() is more closely related to * linitial() than lfirst(): given a List, lsecond() returns the data * in the second list cell. */ #define lfirst(lc) ((lc)->ptr_value) #define lfirst_int(lc) ((lc)->int_value) #define lfirst_oid(lc) ((lc)->oid_value) #define lfirst_xid(lc) ((lc)->xid_value) #define lfirst_node(type,lc) castNode(type, lfirst(lc)) #define linitial(l) lfirst(list_nth_cell(l, 0)) #define linitial_int(l) lfirst_int(list_nth_cell(l, 0)) #define linitial_oid(l) lfirst_oid(list_nth_cell(l, 0)) #define linitial_node(type,l) castNode(type, linitial(l)) #define lsecond(l) lfirst(list_nth_cell(l, 1)) #define lsecond_int(l) lfirst_int(list_nth_cell(l, 1)) #define lsecond_oid(l) lfirst_oid(list_nth_cell(l, 1)) #define lsecond_node(type,l) castNode(type, lsecond(l)) #define lthird(l) lfirst(list_nth_cell(l, 2)) #define lthird_int(l) lfirst_int(list_nth_cell(l, 2)) #define lthird_oid(l) lfirst_oid(list_nth_cell(l, 2)) #define lthird_node(type,l) castNode(type, lthird(l)) #define lfourth(l) lfirst(list_nth_cell(l, 3)) #define lfourth_int(l) lfirst_int(list_nth_cell(l, 3)) #define lfourth_oid(l) lfirst_oid(list_nth_cell(l, 3)) #define lfourth_node(type,l) castNode(type, lfourth(l)) #define llast(l) lfirst(list_last_cell(l)) #define llast_int(l) lfirst_int(list_last_cell(l)) #define llast_oid(l) lfirst_oid(list_last_cell(l)) #define llast_xid(l) lfirst_xid(list_last_cell(l)) #define llast_node(type,l) castNode(type, llast(l)) /* * Convenience macros for building fixed-length lists */ #define list_make_ptr_cell(v) ((ListCell) {.ptr_value = (v)}) #define list_make_int_cell(v) ((ListCell) {.int_value = (v)}) #define list_make_oid_cell(v) ((ListCell) {.oid_value = (v)}) #define list_make_xid_cell(v) ((ListCell) {.xid_value = (v)}) #define list_make1(x1) \ list_make1_impl(T_List, list_make_ptr_cell(x1)) #define list_make2(x1,x2) \ list_make2_impl(T_List, list_make_ptr_cell(x1), list_make_ptr_cell(x2)) #define list_make3(x1,x2,x3) \ list_make3_impl(T_List, list_make_ptr_cell(x1), list_make_ptr_cell(x2), \ list_make_ptr_cell(x3)) #define list_make4(x1,x2,x3,x4) \ list_make4_impl(T_List, list_make_ptr_cell(x1), list_make_ptr_cell(x2), \ list_make_ptr_cell(x3), list_make_ptr_cell(x4)) #define list_make5(x1,x2,x3,x4,x5) \ list_make5_impl(T_List, list_make_ptr_cell(x1), list_make_ptr_cell(x2), \ list_make_ptr_cell(x3), list_make_ptr_cell(x4), \ list_make_ptr_cell(x5)) #define list_make1_int(x1) \ list_make1_impl(T_IntList, list_make_int_cell(x1)) #define list_make2_int(x1,x2) \ list_make2_impl(T_IntList, list_make_int_cell(x1), list_make_int_cell(x2)) #define list_make3_int(x1,x2,x3) \ list_make3_impl(T_IntList, list_make_int_cell(x1), list_make_int_cell(x2), \ list_make_int_cell(x3)) #define list_make4_int(x1,x2,x3,x4) \ list_make4_impl(T_IntList, list_make_int_cell(x1), list_make_int_cell(x2), \ list_make_int_cell(x3), list_make_int_cell(x4)) #define list_make5_int(x1,x2,x3,x4,x5) \ list_make5_impl(T_IntList, list_make_int_cell(x1), list_make_int_cell(x2), \ list_make_int_cell(x3), list_make_int_cell(x4), \ list_make_int_cell(x5)) #define list_make1_oid(x1) \ list_make1_impl(T_OidList, list_make_oid_cell(x1)) #define list_make2_oid(x1,x2) \ list_make2_impl(T_OidList, list_make_oid_cell(x1), list_make_oid_cell(x2)) #define list_make3_oid(x1,x2,x3) \ list_make3_impl(T_OidList, list_make_oid_cell(x1), list_make_oid_cell(x2), \ list_make_oid_cell(x3)) #define list_make4_oid(x1,x2,x3,x4) \ list_make4_impl(T_OidList, list_make_oid_cell(x1), list_make_oid_cell(x2), \ list_make_oid_cell(x3), list_make_oid_cell(x4)) #define list_make5_oid(x1,x2,x3,x4,x5) \ list_make5_impl(T_OidList, list_make_oid_cell(x1), list_make_oid_cell(x2), \ list_make_oid_cell(x3), list_make_oid_cell(x4), \ list_make_oid_cell(x5)) #define list_make1_xid(x1) \ list_make1_impl(T_XidList, list_make_xid_cell(x1)) #define list_make2_xid(x1,x2) \ list_make2_impl(T_XidList, list_make_xid_cell(x1), list_make_xid_cell(x2)) #define list_make3_xid(x1,x2,x3) \ list_make3_impl(T_XidList, list_make_xid_cell(x1), list_make_xid_cell(x2), \ list_make_xid_cell(x3)) #define list_make4_xid(x1,x2,x3,x4) \ list_make4_impl(T_XidList, list_make_xid_cell(x1), list_make_xid_cell(x2), \ list_make_xid_cell(x3), list_make_xid_cell(x4)) #define list_make5_xid(x1,x2,x3,x4,x5) \ list_make5_impl(T_XidList, list_make_xid_cell(x1), list_make_xid_cell(x2), \ list_make_xid_cell(x3), list_make_xid_cell(x4), \ list_make_xid_cell(x5)) /* * Locate the n'th cell (counting from 0) of the list. * It is an assertion failure if there is no such cell. */ static inline ListCell * list_nth_cell(const List *list, int n) { Assert(list != NIL); Assert(n >= 0 && n < list->length); return &list->elements[n]; } /* * Return the last cell in a non-NIL List. */ static inline ListCell * list_last_cell(const List *list) { Assert(list != NIL); return &list->elements[list->length - 1]; } /* * Return the pointer value contained in the n'th element of the * specified list. (List elements begin at 0.) */ static inline void * list_nth(const List *list, int n) { Assert(IsA(list, List)); return lfirst(list_nth_cell(list, n)); } /* * Return the integer value contained in the n'th element of the * specified list. */ static inline int list_nth_int(const List *list, int n) { Assert(IsA(list, IntList)); return lfirst_int(list_nth_cell(list, n)); } /* * Return the OID value contained in the n'th element of the specified * list. */ static inline Oid list_nth_oid(const List *list, int n) { Assert(IsA(list, OidList)); return lfirst_oid(list_nth_cell(list, n)); } #define list_nth_node(type,list,n) castNode(type, list_nth(list, n)) /* * Get the given ListCell's index (from 0) in the given List. */ static inline int list_cell_number(const List *l, const ListCell *c) { Assert(c >= &l->elements[0] && c < &l->elements[l->length]); return c - l->elements; } /* * Get the address of the next cell after "c" within list "l", or NULL if none. */ static inline ListCell * lnext(const List *l, const ListCell *c) { Assert(c >= &l->elements[0] && c < &l->elements[l->length]); c++; if (c < &l->elements[l->length]) return (ListCell *) c; else return NULL; } /* * foreach - * a convenience macro for looping through a list * * "cell" must be the name of a "ListCell *" variable; it's made to point * to each List element in turn. "cell" will be NULL after normal exit from * the loop, but an early "break" will leave it pointing at the current * List element. * * Beware of changing the List object while the loop is iterating. * The current semantics are that we examine successive list indices in * each iteration, so that insertion or deletion of list elements could * cause elements to be re-visited or skipped unexpectedly. Previous * implementations of foreach() behaved differently. However, it's safe * to append elements to the List (or in general, insert them after the * current element); such new elements are guaranteed to be visited. * Also, the current element of the List can be deleted, if you use * foreach_delete_current() to do so. BUT: either of these actions will * invalidate the "cell" pointer for the remainder of the current iteration. */ #define foreach(cell, lst) \ for (ForEachState cell##__state = {(lst), 0}; \ (cell##__state.l != NIL && \ cell##__state.i < cell##__state.l->length) ? \ (cell = &cell##__state.l->elements[cell##__state.i], true) : \ (cell = NULL, false); \ cell##__state.i++) /* * foreach_delete_current - * delete the current list element from the List associated with a * surrounding foreach() loop, returning the new List pointer. * * This is similar to list_delete_cell(), but it also works when using * for_each_xyz macros that don't require passing in a "ListCell *". * Furthermore it adjusts the foreach loop's state so that no list elements * will be missed. Do not delete elements from an active foreach loop's list in * any other way! */ #define foreach_delete_current(lst, var) \ ((List *) (var##__state.l = list_delete_cell(lst, &var##__state.l->elements[var##__state.i--]))) /* * foreach_current_index - * get the zero-based list index of a surrounding foreach() loop's * current element; pass the name of the "ListCell *" iterator variable. * * Beware of using this after foreach_delete_current(); the value will be * out of sync for the rest of the current loop iteration. Anyway, since * you just deleted the current element, the value is pretty meaningless. */ #define foreach_current_index(cell) (cell##__state.i) /* * for_each_from - * Like foreach(), but start from the N'th (zero-based) list element, * not necessarily the first one. * * It's okay for N to exceed the list length, but not for it to be negative. * * The caveats for foreach() apply equally here. */ #define for_each_from(cell, lst, N) \ for (ForEachState cell##__state = for_each_from_setup(lst, N); \ (cell##__state.l != NIL && \ cell##__state.i < cell##__state.l->length) ? \ (cell = &cell##__state.l->elements[cell##__state.i], true) : \ (cell = NULL, false); \ cell##__state.i++) static inline ForEachState for_each_from_setup(const List *lst, int N) { ForEachState r = {lst, N}; Assert(N >= 0); return r; } /* * for_each_cell - * a convenience macro which loops through a list starting from a * specified cell * * The caveats for foreach() apply equally here. */ #define for_each_cell(cell, lst, initcell) \ for (ForEachState cell##__state = for_each_cell_setup(lst, initcell); \ (cell##__state.l != NIL && \ cell##__state.i < cell##__state.l->length) ? \ (cell = &cell##__state.l->elements[cell##__state.i], true) : \ (cell = NULL, false); \ cell##__state.i++) static inline ForEachState for_each_cell_setup(const List *lst, const ListCell *initcell) { ForEachState r = {lst, initcell ? list_cell_number(lst, initcell) : list_length(lst)}; return r; } #define foreach_internal(type, pointer, var, lst, func) \ for (ForEachState var##__state = {(lst), 0}; \ (var##__state.l != NIL && \ var##__state.i < var##__state.l->length && \ (var = func(&var##__state.l->elements[var##__state.i]), true)); \ var##__state.i++) /* * Convenience macros that loop through a list of pointers/ints/oids/xids * without needing a "ListCell *", just a declared variable to store of the * respective type to store the current value in. * * Unlike with foreach() it's not possible to detect if an early "break" * occured by checking the value of the loop variable at the end of the loop. * If you need this, it's recommended to use foreach() instead or manually * track if a break occured by using a boolean flag variable called e.g. * "found". * * The caveats for foreach() apply equally here. */ #define foreach_ptr(type, var, lst) foreach_internal(type, *, var, lst, lfirst) #define foreach_int(var, lst) foreach_internal(int, , var, lst, lfirst_int) #define foreach_oid(var, lst) foreach_internal(Oid, , var, lst, lfirst_oid) #define foreach_xid(var, lst) foreach_internal(TransactionId, , var, lst, lfirst_xid) /* * foreach_node - * The same as foreach_ptr, but when assertions are enabled it verifies that * the element is of the specified node type (using its nodeTag()). */ #define foreach_node(type, var, lst) \ for (ForEachState var##__state = {(lst), 0}; \ (var##__state.l != NIL && \ var##__state.i < var##__state.l->length && \ (var = lfirst_node(type, &var##__state.l->elements[var##__state.i]), true));\ var##__state.i++) /* * forboth - * a convenience macro for advancing through two linked lists * simultaneously. This macro loops through both lists at the same * time, stopping when either list runs out of elements. Depending * on the requirements of the call site, it may also be wise to * assert that the lengths of the two lists are equal. (But, if they * are not, some callers rely on the ending cell values being separately * NULL or non-NULL as defined here; don't try to optimize that.) * * The caveats for foreach() apply equally here. */ #define forboth(cell1, list1, cell2, list2) \ for (ForBothState cell1##__state = {(list1), (list2), 0}; \ multi_for_advance_cell(cell1, cell1##__state, l1, i), \ multi_for_advance_cell(cell2, cell1##__state, l2, i), \ (cell1 != NULL && cell2 != NULL); \ cell1##__state.i++) #define multi_for_advance_cell(cell, state, l, i) \ (cell = (state.l != NIL && state.i < state.l->length) ? \ &state.l->elements[state.i] : NULL) /* * for_both_cell - * a convenience macro which loops through two lists starting from the * specified cells of each. This macro loops through both lists at the same * time, stopping when either list runs out of elements. Depending on the * requirements of the call site, it may also be wise to assert that the * lengths of the two lists are equal, and initcell1 and initcell2 are at * the same position in the respective lists. * * The caveats for foreach() apply equally here. */ #define for_both_cell(cell1, list1, initcell1, cell2, list2, initcell2) \ for (ForBothCellState cell1##__state = \ for_both_cell_setup(list1, initcell1, list2, initcell2); \ multi_for_advance_cell(cell1, cell1##__state, l1, i1), \ multi_for_advance_cell(cell2, cell1##__state, l2, i2), \ (cell1 != NULL && cell2 != NULL); \ cell1##__state.i1++, cell1##__state.i2++) static inline ForBothCellState for_both_cell_setup(const List *list1, const ListCell *initcell1, const List *list2, const ListCell *initcell2) { ForBothCellState r = {list1, list2, initcell1 ? list_cell_number(list1, initcell1) : list_length(list1), initcell2 ? list_cell_number(list2, initcell2) : list_length(list2)}; return r; } /* * forthree - * the same for three lists */ #define forthree(cell1, list1, cell2, list2, cell3, list3) \ for (ForThreeState cell1##__state = {(list1), (list2), (list3), 0}; \ multi_for_advance_cell(cell1, cell1##__state, l1, i), \ multi_for_advance_cell(cell2, cell1##__state, l2, i), \ multi_for_advance_cell(cell3, cell1##__state, l3, i), \ (cell1 != NULL && cell2 != NULL && cell3 != NULL); \ cell1##__state.i++) /* * forfour - * the same for four lists */ #define forfour(cell1, list1, cell2, list2, cell3, list3, cell4, list4) \ for (ForFourState cell1##__state = {(list1), (list2), (list3), (list4), 0}; \ multi_for_advance_cell(cell1, cell1##__state, l1, i), \ multi_for_advance_cell(cell2, cell1##__state, l2, i), \ multi_for_advance_cell(cell3, cell1##__state, l3, i), \ multi_for_advance_cell(cell4, cell1##__state, l4, i), \ (cell1 != NULL && cell2 != NULL && cell3 != NULL && cell4 != NULL); \ cell1##__state.i++) /* * forfive - * the same for five lists */ #define forfive(cell1, list1, cell2, list2, cell3, list3, cell4, list4, cell5, list5) \ for (ForFiveState cell1##__state = {(list1), (list2), (list3), (list4), (list5), 0}; \ multi_for_advance_cell(cell1, cell1##__state, l1, i), \ multi_for_advance_cell(cell2, cell1##__state, l2, i), \ multi_for_advance_cell(cell3, cell1##__state, l3, i), \ multi_for_advance_cell(cell4, cell1##__state, l4, i), \ multi_for_advance_cell(cell5, cell1##__state, l5, i), \ (cell1 != NULL && cell2 != NULL && cell3 != NULL && \ cell4 != NULL && cell5 != NULL); \ cell1##__state.i++) /* Functions in src/backend/nodes/list.c */ extern List *list_make1_impl(NodeTag t, ListCell datum1); extern List *list_make2_impl(NodeTag t, ListCell datum1, ListCell datum2); extern List *list_make3_impl(NodeTag t, ListCell datum1, ListCell datum2, ListCell datum3); extern List *list_make4_impl(NodeTag t, ListCell datum1, ListCell datum2, ListCell datum3, ListCell datum4); extern List *list_make5_impl(NodeTag t, ListCell datum1, ListCell datum2, ListCell datum3, ListCell datum4, ListCell datum5); extern pg_nodiscard List *lappend(List *list, void *datum); extern pg_nodiscard List *lappend_int(List *list, int datum); extern pg_nodiscard List *lappend_oid(List *list, Oid datum); extern pg_nodiscard List *lappend_xid(List *list, TransactionId datum); extern pg_nodiscard List *list_insert_nth(List *list, int pos, void *datum); extern pg_nodiscard List *list_insert_nth_int(List *list, int pos, int datum); extern pg_nodiscard List *list_insert_nth_oid(List *list, int pos, Oid datum); extern pg_nodiscard List *lcons(void *datum, List *list); extern pg_nodiscard List *lcons_int(int datum, List *list); extern pg_nodiscard List *lcons_oid(Oid datum, List *list); extern pg_nodiscard List *list_concat(List *list1, const List *list2); extern pg_nodiscard List *list_concat_copy(const List *list1, const List *list2); extern pg_nodiscard List *list_truncate(List *list, int new_size); extern bool list_member(const List *list, const void *datum); extern bool list_member_ptr(const List *list, const void *datum); extern bool list_member_int(const List *list, int datum); extern bool list_member_oid(const List *list, Oid datum); extern bool list_member_xid(const List *list, TransactionId datum); extern pg_nodiscard List *list_delete(List *list, void *datum); extern pg_nodiscard List *list_delete_ptr(List *list, void *datum); extern pg_nodiscard List *list_delete_int(List *list, int datum); extern pg_nodiscard List *list_delete_oid(List *list, Oid datum); extern pg_nodiscard List *list_delete_first(List *list); extern pg_nodiscard List *list_delete_last(List *list); extern pg_nodiscard List *list_delete_first_n(List *list, int n); extern pg_nodiscard List *list_delete_nth_cell(List *list, int n); extern pg_nodiscard List *list_delete_cell(List *list, ListCell *cell); extern List *list_union(const List *list1, const List *list2); extern List *list_union_ptr(const List *list1, const List *list2); extern List *list_union_int(const List *list1, const List *list2); extern List *list_union_oid(const List *list1, const List *list2); extern List *list_intersection(const List *list1, const List *list2); extern List *list_intersection_int(const List *list1, const List *list2); /* currently, there's no need for list_intersection_ptr etc */ extern List *list_difference(const List *list1, const List *list2); extern List *list_difference_ptr(const List *list1, const List *list2); extern List *list_difference_int(const List *list1, const List *list2); extern List *list_difference_oid(const List *list1, const List *list2); extern pg_nodiscard List *list_append_unique(List *list, void *datum); extern pg_nodiscard List *list_append_unique_ptr(List *list, void *datum); extern pg_nodiscard List *list_append_unique_int(List *list, int datum); extern pg_nodiscard List *list_append_unique_oid(List *list, Oid datum); extern pg_nodiscard List *list_concat_unique(List *list1, const List *list2); extern pg_nodiscard List *list_concat_unique_ptr(List *list1, const List *list2); extern pg_nodiscard List *list_concat_unique_int(List *list1, const List *list2); extern pg_nodiscard List *list_concat_unique_oid(List *list1, const List *list2); extern void list_deduplicate_oid(List *list); extern void list_free(List *list); extern void list_free_deep(List *list); extern pg_nodiscard List *list_copy(const List *oldlist); extern pg_nodiscard List *list_copy_head(const List *oldlist, int len); extern pg_nodiscard List *list_copy_tail(const List *oldlist, int nskip); extern pg_nodiscard List *list_copy_deep(const List *oldlist); typedef int (*list_sort_comparator) (const ListCell *a, const ListCell *b); extern void list_sort(List *list, list_sort_comparator cmp); extern int list_int_cmp(const ListCell *p1, const ListCell *p2); extern int list_oid_cmp(const ListCell *p1, const ListCell *p2); #endif /* PG_LIST_H */ extern inline uint32_t do_something_macro(List *intlist){ uint32_t sum = 0; int myint; foreach_int(myint, intlist) { sum += myint; printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); } return sum; } /* extern inline uint32_t do_something(List *intlist){ uint32_t sum = 0; int myint; for (ForEachState myint__state = {(intlist), 0}; (myint__state.l != NIL && myint__state.i < myint__state.l->length && (myint = lfirst_int(&myint__state.l->elements[myint__state.i]), true)); myint__state.i++) { sum += myint; } return sum; } */
c source #2
Output
Compile to binary object
Link to binary
Execute the code
Intel asm syntax
Demangle identifiers
Verbose demangling
Filters
Unused labels
Library functions
Directives
Comments
Horizontal whitespace
Debug intrinsics
Compiler
6502 cc65 2.17
6502 cc65 2.18
6502 cc65 2.19
6502 cc65 trunk
ARM GCC 10.2.0 (linux)
ARM GCC 10.2.1 (none)
ARM GCC 10.3.0 (linux)
ARM GCC 10.3.1 (2021.07 none)
ARM GCC 10.3.1 (2021.10 none)
ARM GCC 10.5.0
ARM GCC 11.1.0 (linux)
ARM GCC 11.2.0 (linux)
ARM GCC 11.2.1 (none)
ARM GCC 11.3.0 (linux)
ARM GCC 11.4.0
ARM GCC 12.1.0 (linux)
ARM GCC 12.2.0 (linux)
ARM GCC 12.3.0
ARM GCC 12.4.0
ARM GCC 13.1.0 (linux)
ARM GCC 13.2.0
ARM GCC 13.2.0 (unknown-eabi)
ARM GCC 13.3.0
ARM GCC 13.3.0 (unknown-eabi)
ARM GCC 14.1.0
ARM GCC 14.1.0 (unknown-eabi)
ARM GCC 14.2.0
ARM GCC 14.2.0 (unknown-eabi)
ARM GCC 4.5.4 (linux)
ARM GCC 4.6.4 (linux)
ARM GCC 5.4 (linux)
ARM GCC 5.4.1 (none)
ARM GCC 6.3.0 (linux)
ARM GCC 6.4.0 (linux)
ARM GCC 7.2.1 (none)
ARM GCC 7.3.0 (linux)
ARM GCC 7.5.0 (linux)
ARM GCC 8.2.0 (WinCE)
ARM GCC 8.2.0 (linux)
ARM GCC 8.3.1 (none)
ARM GCC 8.5.0 (linux)
ARM GCC 9.2.1 (none)
ARM GCC 9.3.0 (linux)
ARM GCC trunk (linux)
ARM msvc v19.0 (WINE)
ARM msvc v19.10 (WINE)
ARM msvc v19.14 (WINE)
ARM64 GCC 10.2.0
ARM64 GCC 10.3.0
ARM64 GCC 10.4.0
ARM64 GCC 10.5.0
ARM64 GCC 11.1.0
ARM64 GCC 11.2.0
ARM64 GCC 11.3.0
ARM64 GCC 11.4.0
ARM64 GCC 12.1.0
ARM64 GCC 12.2.0
ARM64 GCC 12.3.0
ARM64 GCC 12.4.0
ARM64 GCC 13.1.0
ARM64 GCC 13.2.0
ARM64 GCC 13.3.0
ARM64 GCC 14.1.0
ARM64 GCC 14.2.0
ARM64 GCC 4.9.4
ARM64 GCC 5.4
ARM64 GCC 5.5.0
ARM64 GCC 6.3
ARM64 GCC 6.4.0
ARM64 GCC 7.3.0
ARM64 GCC 7.5.0
ARM64 GCC 8.2.0
ARM64 GCC 8.5.0
ARM64 GCC 9.3.0
ARM64 GCC 9.4.0
ARM64 GCC 9.5.0
ARM64 GCC trunk
ARM64 Morello GCC 10.1.0 Alpha 1
ARM64 Morello GCC 10.1.2 Alpha 2
ARM64 msvc v19.14 (WINE)
AVR gcc 10.3.0
AVR gcc 11.1.0
AVR gcc 12.1.0
AVR gcc 12.2.0
AVR gcc 12.3.0
AVR gcc 12.4.0
AVR gcc 13.1.0
AVR gcc 13.2.0
AVR gcc 13.3.0
AVR gcc 14.1.0
AVR gcc 14.2.0
AVR gcc 4.5.4
AVR gcc 4.6.4
AVR gcc 5.4.0
AVR gcc 9.2.0
AVR gcc 9.3.0
Arduino Mega (1.8.9)
Arduino Uno (1.8.9)
BPF clang (trunk)
BPF clang 13.0.0
BPF clang 14.0.0
BPF clang 15.0.0
BPF clang 16.0.0
BPF clang 17.0.1
BPF clang 18.1.0
BPF gcc 13.1.0
BPF gcc 13.2.0
BPF gcc 13.3.0
BPF gcc 14.1.0
BPF gcc 14.2.0
BPF gcc trunk
Chibicc 2020-12-07
FRC 2019
FRC 2020
FRC 2023
HPPA gcc 14.2.0
K1C gcc 7.4
K1C gcc 7.5
KVX ACB 4.1.0 (GCC 7.5.0)
KVX ACB 4.1.0-cd1 (GCC 7.5.0)
KVX ACB 4.10.0 (GCC 10.3.1)
KVX ACB 4.11.1 (GCC 10.3.1)
KVX ACB 4.12.0 (GCC 11.3.0)
KVX ACB 4.2.0 (GCC 7.5.0)
KVX ACB 4.3.0 (GCC 7.5.0)
KVX ACB 4.4.0 (GCC 7.5.0)
KVX ACB 4.6.0 (GCC 9.4.1)
KVX ACB 4.8.0 (GCC 9.4.1)
KVX ACB 4.9.0 (GCC 9.4.1)
KVX ACB 5.0.0 (GCC 12.2.1)
KVX ACB 5.2.0 (GCC 13.2.1)
LC3 (trunk)
M68K clang (trunk)
M68K gcc 13.1.0
M68K gcc 13.2.0
M68K gcc 13.3.0
M68K gcc 14.1.0
M68K gcc 14.2.0
MRISC32 gcc (trunk)
MSP430 gcc 12.1.0
MSP430 gcc 12.2.0
MSP430 gcc 12.3.0
MSP430 gcc 12.4.0
MSP430 gcc 13.1.0
MSP430 gcc 13.2.0
MSP430 gcc 13.3.0
MSP430 gcc 14.1.0
MSP430 gcc 14.2.0
MSP430 gcc 4.5.3
MSP430 gcc 5.3.0
MSP430 gcc 6.2.1
MinGW clang 14.0.3
MinGW clang 14.0.6
MinGW clang 15.0.7
MinGW clang 16.0.0
MinGW clang 16.0.2
MinGW gcc 11.3.0
MinGW gcc 12.1.0
MinGW gcc 12.2.0
MinGW gcc 13.1.0
POWER64 gcc 11.2.0
POWER64 gcc 12.1.0
POWER64 gcc 12.2.0
POWER64 gcc 12.3.0
POWER64 gcc 12.4.0
POWER64 gcc 13.1.0
POWER64 gcc 13.2.0
POWER64 gcc 13.3.0
POWER64 gcc 14.1.0
POWER64 gcc 14.2.0
POWER64 gcc trunk
RISC-V (32-bits) gcc (trunk)
RISC-V (32-bits) gcc 10.2.0
RISC-V (32-bits) gcc 10.3.0
RISC-V (32-bits) gcc 11.2.0
RISC-V (32-bits) gcc 11.3.0
RISC-V (32-bits) gcc 11.4.0
RISC-V (32-bits) gcc 12.1.0
RISC-V (32-bits) gcc 12.2.0
RISC-V (32-bits) gcc 12.3.0
RISC-V (32-bits) gcc 12.4.0
RISC-V (32-bits) gcc 13.1.0
RISC-V (32-bits) gcc 13.2.0
RISC-V (32-bits) gcc 13.3.0
RISC-V (32-bits) gcc 14.1.0
RISC-V (32-bits) gcc 14.2.0
RISC-V (32-bits) gcc 8.2.0
RISC-V (32-bits) gcc 8.5.0
RISC-V (32-bits) gcc 9.4.0
RISC-V (64-bits) gcc (trunk)
RISC-V (64-bits) gcc 10.2.0
RISC-V (64-bits) gcc 10.3.0
RISC-V (64-bits) gcc 11.2.0
RISC-V (64-bits) gcc 11.3.0
RISC-V (64-bits) gcc 11.4.0
RISC-V (64-bits) gcc 12.1.0
RISC-V (64-bits) gcc 12.2.0
RISC-V (64-bits) gcc 12.3.0
RISC-V (64-bits) gcc 12.4.0
RISC-V (64-bits) gcc 13.1.0
RISC-V (64-bits) gcc 13.2.0
RISC-V (64-bits) gcc 13.3.0
RISC-V (64-bits) gcc 14.1.0
RISC-V (64-bits) gcc 14.2.0
RISC-V (64-bits) gcc 8.2.0
RISC-V (64-bits) gcc 8.5.0
RISC-V (64-bits) gcc 9.4.0
RISC-V rv32gc clang (trunk)
RISC-V rv32gc clang 10.0.0
RISC-V rv32gc clang 10.0.1
RISC-V rv32gc clang 11.0.0
RISC-V rv32gc clang 11.0.1
RISC-V rv32gc clang 12.0.0
RISC-V rv32gc clang 12.0.1
RISC-V rv32gc clang 13.0.0
RISC-V rv32gc clang 13.0.1
RISC-V rv32gc clang 14.0.0
RISC-V rv32gc clang 15.0.0
RISC-V rv32gc clang 16.0.0
RISC-V rv32gc clang 17.0.1
RISC-V rv32gc clang 18.1.0
RISC-V rv32gc clang 9.0.0
RISC-V rv32gc clang 9.0.1
RISC-V rv64gc clang (trunk)
RISC-V rv64gc clang 10.0.0
RISC-V rv64gc clang 10.0.1
RISC-V rv64gc clang 11.0.0
RISC-V rv64gc clang 11.0.1
RISC-V rv64gc clang 12.0.0
RISC-V rv64gc clang 12.0.1
RISC-V rv64gc clang 13.0.0
RISC-V rv64gc clang 13.0.1
RISC-V rv64gc clang 14.0.0
RISC-V rv64gc clang 15.0.0
RISC-V rv64gc clang 16.0.0
RISC-V rv64gc clang 17.0.1
RISC-V rv64gc clang 18.1.0
RISC-V rv64gc clang 9.0.0
RISC-V rv64gc clang 9.0.1
Raspbian Buster
Raspbian Stretch
SDCC 4.0.0
SDCC 4.1.0
SDCC 4.2.0
SDCC 4.3.0
SDCC 4.4.0
SPARC LEON gcc 12.2.0
SPARC LEON gcc 12.3.0
SPARC LEON gcc 12.4.0
SPARC LEON gcc 13.1.0
SPARC LEON gcc 13.2.0
SPARC LEON gcc 13.3.0
SPARC LEON gcc 14.1.0
SPARC LEON gcc 14.2.0
SPARC gcc 12.2.0
SPARC gcc 12.3.0
SPARC gcc 12.4.0
SPARC gcc 13.1.0
SPARC gcc 13.2.0
SPARC gcc 13.3.0
SPARC gcc 14.1.0
SPARC gcc 14.2.0
SPARC64 gcc 12.2.0
SPARC64 gcc 12.3.0
SPARC64 gcc 12.4.0
SPARC64 gcc 13.1.0
SPARC64 gcc 13.2.0
SPARC64 gcc 13.3.0
SPARC64 gcc 14.1.0
SPARC64 gcc 14.2.0
TCC (trunk)
TCC 0.9.27
TI C6x gcc 12.2.0
TI C6x gcc 12.3.0
TI C6x gcc 12.4.0
TI C6x gcc 13.1.0
TI C6x gcc 13.2.0
TI C6x gcc 13.3.0
TI C6x gcc 14.1.0
TI C6x gcc 14.2.0
TI CL430 21.6.1
VAX gcc NetBSDELF 10.4.0
VAX gcc NetBSDELF 10.5.0 (Nov 15 03:50:22 2023)
WebAssembly clang (trunk)
Xtensa ESP32 gcc 11.2.0 (2022r1)
Xtensa ESP32 gcc 12.2.0 (20230208)
Xtensa ESP32 gcc 8.2.0 (2019r2)
Xtensa ESP32 gcc 8.2.0 (2020r1)
Xtensa ESP32 gcc 8.2.0 (2020r2)
Xtensa ESP32 gcc 8.4.0 (2020r3)
Xtensa ESP32 gcc 8.4.0 (2021r1)
Xtensa ESP32 gcc 8.4.0 (2021r2)
Xtensa ESP32-S2 gcc 11.2.0 (2022r1)
Xtensa ESP32-S2 gcc 12.2.0 (20230208)
Xtensa ESP32-S2 gcc 8.2.0 (2019r2)
Xtensa ESP32-S2 gcc 8.2.0 (2020r1)
Xtensa ESP32-S2 gcc 8.2.0 (2020r2)
Xtensa ESP32-S2 gcc 8.4.0 (2020r3)
Xtensa ESP32-S2 gcc 8.4.0 (2021r1)
Xtensa ESP32-S2 gcc 8.4.0 (2021r2)
Xtensa ESP32-S3 gcc 11.2.0 (2022r1)
Xtensa ESP32-S3 gcc 12.2.0 (20230208)
Xtensa ESP32-S3 gcc 8.4.0 (2020r3)
Xtensa ESP32-S3 gcc 8.4.0 (2021r1)
Xtensa ESP32-S3 gcc 8.4.0 (2021r2)
arm64 msvc v19.20 VS16.0
arm64 msvc v19.21 VS16.1
arm64 msvc v19.22 VS16.2
arm64 msvc v19.23 VS16.3
arm64 msvc v19.24 VS16.4
arm64 msvc v19.25 VS16.5
arm64 msvc v19.27 VS16.7
arm64 msvc v19.28 VS16.8
arm64 msvc v19.28 VS16.9
arm64 msvc v19.29 VS16.10
arm64 msvc v19.29 VS16.11
arm64 msvc v19.30 VS17.0
arm64 msvc v19.31 VS17.1
arm64 msvc v19.32 VS17.2
arm64 msvc v19.33 VS17.3
arm64 msvc v19.34 VS17.4
arm64 msvc v19.35 VS17.5
arm64 msvc v19.36 VS17.6
arm64 msvc v19.37 VS17.7
arm64 msvc v19.38 VS17.8
arm64 msvc v19.39 VS17.9
arm64 msvc v19.40 VS17.10
arm64 msvc v19.latest
armv7-a clang (trunk)
armv7-a clang 10.0.0
armv7-a clang 10.0.1
armv7-a clang 11.0.0
armv7-a clang 11.0.1
armv7-a clang 12.0.0
armv7-a clang 12.0.1
armv7-a clang 13.0.0
armv7-a clang 13.0.1
armv7-a clang 14.0.0
armv7-a clang 15.0.0
armv7-a clang 16.0.0
armv7-a clang 17.0.1
armv7-a clang 18.1.0
armv7-a clang 9.0.0
armv7-a clang 9.0.1
armv8-a clang (all architectural features, trunk)
armv8-a clang (trunk)
armv8-a clang 10.0.0
armv8-a clang 10.0.1
armv8-a clang 11.0.0
armv8-a clang 11.0.1
armv8-a clang 12.0.0
armv8-a clang 12.0.1
armv8-a clang 13.0.0
armv8-a clang 13.0.1
armv8-a clang 14.0.0
armv8-a clang 15.0.0
armv8-a clang 16.0.0
armv8-a clang 17.0.1
armv8-a clang 18.1.0
armv8-a clang 9.0.0
armv8-a clang 9.0.1
clang 12 for DPU (rel 2023.2.0)
cproc-master
llvm-mos commander X16
llvm-mos commodore 64
llvm-mos mega65
llvm-mos nes-cnrom
llvm-mos nes-mmc1
llvm-mos nes-mmc3
llvm-mos nes-nrom
llvm-mos osi-c1p
loongarch64 gcc 12.2.0
loongarch64 gcc 12.3.0
loongarch64 gcc 12.4.0
loongarch64 gcc 13.1.0
loongarch64 gcc 13.2.0
loongarch64 gcc 13.3.0
loongarch64 gcc 14.1.0
loongarch64 gcc 14.2.0
mips (el) gcc 12.1.0
mips (el) gcc 12.2.0
mips (el) gcc 12.3.0
mips (el) gcc 12.4.0
mips (el) gcc 13.1.0
mips (el) gcc 13.2.0
mips (el) gcc 13.3.0
mips (el) gcc 14.1.0
mips (el) gcc 14.2.0
mips (el) gcc 4.9.4
mips (el) gcc 5.4
mips (el) gcc 5.5.0
mips (el) gcc 9.5.0
mips clang 13.0.0
mips clang 14.0.0
mips clang 15.0.0
mips clang 16.0.0
mips clang 17.0.1
mips clang 18.1.0
mips gcc 11.2.0
mips gcc 12.1.0
mips gcc 12.2.0
mips gcc 12.3.0
mips gcc 12.4.0
mips gcc 13.1.0
mips gcc 13.2.0
mips gcc 13.3.0
mips gcc 14.1.0
mips gcc 14.2.0
mips gcc 4.9.4
mips gcc 5.4
mips gcc 5.5.0
mips gcc 9.3.0 (codescape)
mips gcc 9.5.0
mips64 (el) gcc 12.1.0
mips64 (el) gcc 12.2.0
mips64 (el) gcc 12.3.0
mips64 (el) gcc 12.4.0
mips64 (el) gcc 13.1.0
mips64 (el) gcc 13.2.0
mips64 (el) gcc 13.3.0
mips64 (el) gcc 14.1.0
mips64 (el) gcc 14.2.0
mips64 (el) gcc 4.9.4
mips64 (el) gcc 5.4.0
mips64 (el) gcc 5.5.0
mips64 (el) gcc 9.5.0
mips64 clang 13.0.0
mips64 clang 14.0.0
mips64 clang 15.0.0
mips64 clang 16.0.0
mips64 clang 17.0.1
mips64 clang 18.1.0
mips64 gcc 11.2.0
mips64 gcc 12.1.0
mips64 gcc 12.2.0
mips64 gcc 12.3.0
mips64 gcc 12.4.0
mips64 gcc 13.1.0
mips64 gcc 13.2.0
mips64 gcc 13.3.0
mips64 gcc 14.1.0
mips64 gcc 14.2.0
mips64 gcc 4.9.4
mips64 gcc 5.4
mips64 gcc 5.5.0
mips64 gcc 9.5.0
mips64el clang 13.0.0
mips64el clang 14.0.0
mips64el clang 15.0.0
mips64el clang 16.0.0
mips64el clang 17.0.1
mips64el clang 18.1.0
mipsel clang 13.0.0
mipsel clang 14.0.0
mipsel clang 15.0.0
mipsel clang 16.0.0
mipsel clang 17.0.1
mipsel clang 18.1.0
movfuscator (trunk)
nanoMIPS gcc 6.3.0
power gcc 11.2.0
power gcc 12.1.0
power gcc 12.2.0
power gcc 12.3.0
power gcc 12.4.0
power gcc 13.1.0
power gcc 13.2.0
power gcc 13.3.0
power gcc 14.1.0
power gcc 14.2.0
power gcc 4.8.5
power64 AT12.0 (gcc8)
power64 AT13.0 (gcc9)
power64le AT12.0 (gcc8)
power64le AT13.0 (gcc9)
power64le clang (trunk)
power64le gcc 11.2.0
power64le gcc 12.1.0
power64le gcc 12.2.0
power64le gcc 12.3.0
power64le gcc 12.4.0
power64le gcc 13.1.0
power64le gcc 13.2.0
power64le gcc 13.3.0
power64le gcc 14.1.0
power64le gcc 14.2.0
power64le gcc 6.3.0
power64le gcc trunk
powerpc64 clang (trunk)
ppci 0.5.5
s390x gcc 11.2.0
s390x gcc 12.1.0
s390x gcc 12.2.0
s390x gcc 12.3.0
s390x gcc 12.4.0
s390x gcc 13.1.0
s390x gcc 13.2.0
s390x gcc 13.3.0
s390x gcc 14.1.0
s390x gcc 14.2.0
sh gcc 12.2.0
sh gcc 12.3.0
sh gcc 12.4.0
sh gcc 13.1.0
sh gcc 13.2.0
sh gcc 13.3.0
sh gcc 14.1.0
sh gcc 14.2.0
sh gcc 4.9.4
sh gcc 9.5.0
vast (trunk)
x64 msvc v19.0 (WINE)
x64 msvc v19.10 (WINE)
x64 msvc v19.14 (WINE)
x64 msvc v19.20 VS16.0
x64 msvc v19.21 VS16.1
x64 msvc v19.22 VS16.2
x64 msvc v19.23 VS16.3
x64 msvc v19.24 VS16.4
x64 msvc v19.25 VS16.5
x64 msvc v19.27 VS16.7
x64 msvc v19.28 VS16.8
x64 msvc v19.28 VS16.9
x64 msvc v19.29 VS16.10
x64 msvc v19.29 VS16.11
x64 msvc v19.30 VS17.0
x64 msvc v19.31 VS17.1
x64 msvc v19.32 VS17.2
x64 msvc v19.33 VS17.3
x64 msvc v19.34 VS17.4
x64 msvc v19.35 VS17.5
x64 msvc v19.36 VS17.6
x64 msvc v19.37 VS17.7
x64 msvc v19.38 VS17.8
x64 msvc v19.39 VS17.9
x64 msvc v19.40 VS17.10
x64 msvc v19.latest
x86 CompCert 3.10
x86 CompCert 3.11
x86 CompCert 3.12
x86 CompCert 3.9
x86 gcc 1.27
x86 msvc v19.0 (WINE)
x86 msvc v19.10 (WINE)
x86 msvc v19.14 (WINE)
x86 msvc v19.20 VS16.0
x86 msvc v19.21 VS16.1
x86 msvc v19.22 VS16.2
x86 msvc v19.23 VS16.3
x86 msvc v19.24 VS16.4
x86 msvc v19.25 VS16.5
x86 msvc v19.27 VS16.7
x86 msvc v19.28 VS16.8
x86 msvc v19.28 VS16.9
x86 msvc v19.29 VS16.10
x86 msvc v19.29 VS16.11
x86 msvc v19.30 VS17.0
x86 msvc v19.31 VS17.1
x86 msvc v19.32 VS17.2
x86 msvc v19.33 VS17.3
x86 msvc v19.34 VS17.4
x86 msvc v19.35 VS17.5
x86 msvc v19.36 VS17.6
x86 msvc v19.37 VS17.7
x86 msvc v19.38 VS17.8
x86 msvc v19.39 VS17.9
x86 msvc v19.40 VS17.10
x86 msvc v19.latest
x86 nvc 24.9
x86 tendra (trunk)
x86-64 clang (assertions trunk)
x86-64 clang (thephd.dev)
x86-64 clang (trunk)
x86-64 clang (widberg)
x86-64 clang 10.0.0
x86-64 clang 10.0.1
x86-64 clang 11.0.0
x86-64 clang 11.0.1
x86-64 clang 12.0.0
x86-64 clang 12.0.1
x86-64 clang 13.0.0
x86-64 clang 13.0.1
x86-64 clang 14.0.0
x86-64 clang 15.0.0
x86-64 clang 16.0.0
x86-64 clang 17.0.1
x86-64 clang 18.1.0
x86-64 clang 19.1.0
x86-64 clang 3.0.0
x86-64 clang 3.1
x86-64 clang 3.2
x86-64 clang 3.3
x86-64 clang 3.4.1
x86-64 clang 3.5
x86-64 clang 3.5.1
x86-64 clang 3.5.2
x86-64 clang 3.6
x86-64 clang 3.7
x86-64 clang 3.7.1
x86-64 clang 3.8
x86-64 clang 3.8.1
x86-64 clang 3.9.0
x86-64 clang 3.9.1
x86-64 clang 4.0.0
x86-64 clang 4.0.1
x86-64 clang 5.0.0
x86-64 clang 5.0.1
x86-64 clang 5.0.2
x86-64 clang 6.0.0
x86-64 clang 6.0.1
x86-64 clang 7.0.0
x86-64 clang 7.0.1
x86-64 clang 7.1.0
x86-64 clang 8.0.0
x86-64 clang 8.0.1
x86-64 clang 9.0.0
x86-64 clang 9.0.1
x86-64 gcc (trunk)
x86-64 gcc 10.1
x86-64 gcc 10.2
x86-64 gcc 10.3
x86-64 gcc 10.4
x86-64 gcc 10.5
x86-64 gcc 11.1
x86-64 gcc 11.2
x86-64 gcc 11.3
x86-64 gcc 11.4
x86-64 gcc 12.1
x86-64 gcc 12.2
x86-64 gcc 12.3
x86-64 gcc 12.4
x86-64 gcc 13.1
x86-64 gcc 13.2
x86-64 gcc 13.3
x86-64 gcc 14.1
x86-64 gcc 14.2
x86-64 gcc 3.4.6
x86-64 gcc 4.0.4
x86-64 gcc 4.1.2
x86-64 gcc 4.4.7
x86-64 gcc 4.5.3
x86-64 gcc 4.6.4
x86-64 gcc 4.7.1
x86-64 gcc 4.7.2
x86-64 gcc 4.7.3
x86-64 gcc 4.7.4
x86-64 gcc 4.8.1
x86-64 gcc 4.8.2
x86-64 gcc 4.8.3
x86-64 gcc 4.8.4
x86-64 gcc 4.8.5
x86-64 gcc 4.9.0
x86-64 gcc 4.9.1
x86-64 gcc 4.9.2
x86-64 gcc 4.9.3
x86-64 gcc 4.9.4
x86-64 gcc 5.1
x86-64 gcc 5.2
x86-64 gcc 5.3
x86-64 gcc 5.4
x86-64 gcc 6.1
x86-64 gcc 6.2
x86-64 gcc 6.3
x86-64 gcc 6.5
x86-64 gcc 7.1
x86-64 gcc 7.2
x86-64 gcc 7.3
x86-64 gcc 7.4
x86-64 gcc 7.5
x86-64 gcc 8.1
x86-64 gcc 8.2
x86-64 gcc 8.3
x86-64 gcc 8.4
x86-64 gcc 8.5
x86-64 gcc 9.1
x86-64 gcc 9.2
x86-64 gcc 9.3
x86-64 gcc 9.4
x86-64 gcc 9.5
x86-64 icc 13.0.1
x86-64 icc 16.0.3
x86-64 icc 17.0.0
x86-64 icc 18.0.0
x86-64 icc 19.0.0
x86-64 icc 19.0.1
x86-64 icc 2021.1.2
x86-64 icc 2021.10.0
x86-64 icc 2021.2.0
x86-64 icc 2021.3.0
x86-64 icc 2021.4.0
x86-64 icc 2021.5.0
x86-64 icc 2021.6.0
x86-64 icc 2021.7.0
x86-64 icc 2021.7.1
x86-64 icc 2021.8.0
x86-64 icc 2021.9.0
x86-64 icx (latest)
x86-64 icx 2021.1.2
x86-64 icx 2021.2.0
x86-64 icx 2021.3.0
x86-64 icx 2021.4.0
x86-64 icx 2022.0.0
x86-64 icx 2022.1.0
x86-64 icx 2022.2.0
x86-64 icx 2022.2.1
x86-64 icx 2023.0.0
x86-64 icx 2023.1.0
x86-64 icx 2024.0.0
x86_64 CompCert 3.10
x86_64 CompCert 3.11
x86_64 CompCert 3.12
x86_64 CompCert 3.9
z88dk 2.2
zig cc 0.10.0
zig cc 0.11.0
zig cc 0.12.0
zig cc 0.12.1
zig cc 0.13.0
zig cc 0.6.0
zig cc 0.7.0
zig cc 0.7.1
zig cc 0.8.0
zig cc 0.9.0
zig cc trunk
Options
Source code
// Type your code here, or load an example. #include <stdbool.h> #include <stdint.h> /* * * nodes.h * Definitions for tagged nodes. * * * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/nodes/nodes.h * *------------------------------------------------------------------------- */ #ifndef NODES_H #define NODES_H /* * The first field of every node is NodeTag. Each node created (with makeNode) * will have one of the following tags as the value of its first field. * * Note that inserting or deleting node types changes the numbers of other * node types later in the list. This is no problem during development, since * the node numbers are never stored on disk. But don't do it in a released * branch, because that would represent an ABI break for extensions. */ typedef enum NodeTag { T_Invalid = 0, } NodeTag; /* * pg_node_attr() - Used in node definitions to set extra information for * gen_node_support.pl * * Attributes can be attached to a node as a whole (place the attribute * specification on the first line after the struct's opening brace) * or to a specific field (place it at the end of that field's line). The * argument is a comma-separated list of attributes. Unrecognized attributes * cause an error. * * Valid node attributes: * * - abstract: Abstract types are types that cannot be instantiated but that * can be supertypes of other types. We track their fields, so that * subtypes can use them, but we don't emit a node tag, so you can't * instantiate them. * * - custom_copy_equal: Has custom implementations in copyfuncs.c and * equalfuncs.c. * * - custom_read_write: Has custom implementations in outfuncs.c and * readfuncs.c. * * - custom_query_jumble: Has custom implementation in queryjumblefuncs.c. * * - no_copy: Does not support copyObject() at all. * * - no_equal: Does not support equal() at all. * * - no_copy_equal: Shorthand for both no_copy and no_equal. * * - no_query_jumble: Does not support JumbleQuery() at all. * * - no_read: Does not support nodeRead() at all. * * - nodetag_only: Does not support copyObject(), equal(), jumbleQuery() * outNode() or nodeRead(). * * - special_read_write: Has special treatment in outNode() and nodeRead(). * * - nodetag_number(VALUE): assign the specified nodetag number instead of * an auto-generated number. Typically this would only be used in stable * branches, to give a newly-added node type a number without breaking ABI * by changing the numbers of existing node types. * * Node types can be supertypes of other types whether or not they are marked * abstract: if a node struct appears as the first field of another struct * type, then it is the supertype of that type. The no_copy, no_equal, * no_query_jumble and no_read node attributes are automatically inherited * from the supertype. (Notice that nodetag_only does not inherit, so it's * not quite equivalent to a combination of other attributes.) * * Valid node field attributes: * * - array_size(OTHERFIELD): This field is a dynamically allocated array with * size indicated by the mentioned other field. The other field is either a * scalar or a list, in which case the length of the list is used. * * - copy_as(VALUE): In copyObject(), replace the field's value with VALUE. * * - copy_as_scalar: In copyObject(), copy the field as a scalar value * (e.g. a pointer) even if it is a node-type pointer. * * - equal_as_scalar: In equal(), compare the field as a scalar value * even if it is a node-type pointer. * * - equal_ignore: Ignore the field for equality. * * - equal_ignore_if_zero: Ignore the field for equality if it is zero. * (Otherwise, compare normally.) * * - query_jumble_ignore: Ignore the field for the query jumbling. Note * that typmod and collation information are usually irrelevant for the * query jumbling. * * - query_jumble_location: Mark the field as a location to track. This is * only allowed for integer fields that include "location" in their name. * * - read_as(VALUE): In nodeRead(), replace the field's value with VALUE. * * - read_write_ignore: Ignore the field for read/write. This is only allowed * if the node type is marked no_read or read_as() is also specified. * * - write_only_relids, write_only_nondefault_pathtarget, write_only_req_outer: * Special handling for Path struct; see there. * */ #define pg_node_attr(...) /* * The first field of a node of any type is guaranteed to be the NodeTag. * Hence the type of any node can be gotten by casting it to Node. Declaring * a variable to be of Node * (instead of void *) can also facilitate * debugging. */ typedef struct Node { NodeTag type; } Node; #define nodeTag(nodeptr) (((const Node*)(nodeptr))->type) /* * newNode - * create a new node of the specified size and tag the node with the * specified tag. * * !WARNING!: Avoid using newNode directly. You should be using the * macro makeNode. eg. to create a Query node, use makeNode(Query) * * Note: the size argument should always be a compile-time constant, so the * apparent risk of multiple evaluation doesn't matter in practice. */ #ifdef __GNUC__ /* With GCC, we can use a compound statement within an expression */ #define newNode(size, tag) \ ({ Node *_result; \ AssertMacro((size) >= sizeof(Node)); /* need the tag, at least */ \ _result = (Node *) palloc0fast(size); \ _result->type = (tag); \ _result; \ }) #else /* * There is no way to dereference the palloc'ed pointer to assign the * tag, and also return the pointer itself, so we need a holder variable. * Fortunately, this macro isn't recursive so we just define * a global variable for this purpose. */ extern PGDLLIMPORT Node *newNodeMacroHolder; #define newNode(size, tag) \ ( \ AssertMacro((size) >= sizeof(Node)), /* need the tag, at least */ \ newNodeMacroHolder = (Node *) palloc0fast(size), \ newNodeMacroHolder->type = (tag), \ newNodeMacroHolder \ ) #endif /* __GNUC__ */ #define makeNode(_type_) ((_type_ *) newNode(sizeof(_type_),T_##_type_)) #define NodeSetTag(nodeptr,t) (((Node*)(nodeptr))->type = (t)) #define IsA(nodeptr,_type_) (nodeTag(nodeptr) == T_##_type_) /* * castNode(type, ptr) casts ptr to "type *", and if assertions are enabled, * verifies that the node has the appropriate type (using its nodeTag()). * * Use an inline function when assertions are enabled, to avoid multiple * evaluations of the ptr argument (which could e.g. be a function call). */ #ifdef USE_ASSERT_CHECKING static inline Node * castNodeImpl(NodeTag type, void *ptr) { Assert(ptr == NULL || nodeTag(ptr) == type); return (Node *) ptr; } #define castNode(_type_, nodeptr) ((_type_ *) castNodeImpl(T_##_type_, nodeptr)) #else #define castNode(_type_, nodeptr) ((_type_ *) (nodeptr)) #endif /* USE_ASSERT_CHECKING */ /* ---------------------------------------------------------------- * extern declarations follow * ---------------------------------------------------------------- */ /* * nodes/{outfuncs.c,print.c} */ struct Bitmapset; /* not to include bitmapset.h here */ struct StringInfoData; /* not to include stringinfo.h here */ extern void outNode(struct StringInfoData *str, const void *obj); extern void outToken(struct StringInfoData *str, const char *s); extern void outBitmapset(struct StringInfoData *str, const struct Bitmapset *bms); extern void outDatum(struct StringInfoData *str, uintptr_t value, int typlen, bool typbyval); extern char *nodeToString(const void *obj); extern char *bmsToString(const struct Bitmapset *bms); /* * nodes/{readfuncs.c,read.c} */ extern void *stringToNode(const char *str); #ifdef WRITE_READ_PARSE_PLAN_TREES extern void *stringToNodeWithLocations(const char *str); #endif extern struct Bitmapset *readBitmapset(void); extern uintptr_t readDatum(bool typbyval); extern bool *readBoolCols(int numCols); extern int *readIntCols(int numCols); /* * nodes/copyfuncs.c */ extern void *copyObjectImpl(const void *from); /* cast result back to argument type, if supported by compiler */ #ifdef HAVE_TYPEOF #define copyObject(obj) ((typeof(obj)) copyObjectImpl(obj)) #else #define copyObject(obj) copyObjectImpl(obj) #endif /* * nodes/equalfuncs.c */ extern bool equal(const void *a, const void *b); /* * Typedefs for identifying qualifier selectivities and plan costs as such. * These are just plain "double"s, but declaring a variable as Selectivity * or Cost makes the intent more obvious. * * These could have gone into plannodes.h or some such, but many files * depend on them... */ typedef double Selectivity; /* fraction of tuples a qualifier will pass */ typedef double Cost; /* execution cost (in page-access units) */ typedef double Cardinality; /* (estimated) number of rows or other integer * count */ /* * CmdType - * enums for type of operation represented by a Query or PlannedStmt * * This is needed in both parsenodes.h and plannodes.h, so put it here... */ typedef enum CmdType { CMD_UNKNOWN, CMD_SELECT, /* select stmt */ CMD_UPDATE, /* update stmt */ CMD_INSERT, /* insert stmt */ CMD_DELETE, /* delete stmt */ CMD_MERGE, /* merge stmt */ CMD_UTILITY, /* cmds like create, destroy, copy, vacuum, * etc. */ CMD_NOTHING /* dummy command for instead nothing rules * with qual */ } CmdType; /* * JoinType - * enums for types of relation joins * * JoinType determines the exact semantics of joining two relations using * a matching qualification. For example, it tells what to do with a tuple * that has no match in the other relation. * * This is needed in both parsenodes.h and plannodes.h, so put it here... */ typedef enum JoinType { /* * The canonical kinds of joins according to the SQL JOIN syntax. Only * these codes can appear in parser output (e.g., JoinExpr nodes). */ JOIN_INNER, /* matching tuple pairs only */ JOIN_LEFT, /* pairs + unmatched LHS tuples */ JOIN_FULL, /* pairs + unmatched LHS + unmatched RHS */ JOIN_RIGHT, /* pairs + unmatched RHS tuples */ /* * Semijoins and anti-semijoins (as defined in relational theory) do not * appear in the SQL JOIN syntax, but there are standard idioms for * representing them (e.g., using EXISTS). The planner recognizes these * cases and converts them to joins. So the planner and executor must * support these codes. NOTE: in JOIN_SEMI output, it is unspecified * which matching RHS row is joined to. In JOIN_ANTI output, the row is * guaranteed to be null-extended. */ JOIN_SEMI, /* 1 copy of each LHS row that has match(es) */ JOIN_ANTI, /* 1 copy of each LHS row that has no match */ JOIN_RIGHT_ANTI, /* 1 copy of each RHS row that has no match */ /* * These codes are used internally in the planner, but are not supported * by the executor (nor, indeed, by most of the planner). */ JOIN_UNIQUE_OUTER, /* LHS path must be made unique */ JOIN_UNIQUE_INNER /* RHS path must be made unique */ /* * We might need additional join types someday. */ } JoinType; /* * OUTER joins are those for which pushed-down quals must behave differently * from the join's own quals. This is in fact everything except INNER and * SEMI joins. However, this macro must also exclude the JOIN_UNIQUE symbols * since those are temporary proxies for what will eventually be an INNER * join. * * Note: semijoins are a hybrid case, but we choose to treat them as not * being outer joins. This is okay principally because the SQL syntax makes * it impossible to have a pushed-down qual that refers to the inner relation * of a semijoin; so there is no strong need to distinguish join quals from * pushed-down quals. This is convenient because for almost all purposes, * quals attached to a semijoin can be treated the same as innerjoin quals. */ #define IS_OUTER_JOIN(jointype) \ (((1 << (jointype)) & \ ((1 << JOIN_LEFT) | \ (1 << JOIN_FULL) | \ (1 << JOIN_RIGHT) | \ (1 << JOIN_ANTI) | \ (1 << JOIN_RIGHT_ANTI))) != 0) /* * AggStrategy - * overall execution strategies for Agg plan nodes * * This is needed in both pathnodes.h and plannodes.h, so put it here... */ typedef enum AggStrategy { AGG_PLAIN, /* simple agg across all input rows */ AGG_SORTED, /* grouped agg, input must be sorted */ AGG_HASHED, /* grouped agg, use internal hashtable */ AGG_MIXED /* grouped agg, hash and sort both used */ } AggStrategy; /* * AggSplit - * splitting (partial aggregation) modes for Agg plan nodes * * This is needed in both pathnodes.h and plannodes.h, so put it here... */ /* Primitive options supported by nodeAgg.c: */ #define AGGSPLITOP_COMBINE 0x01 /* substitute combinefn for transfn */ #define AGGSPLITOP_SKIPFINAL 0x02 /* skip finalfn, return state as-is */ #define AGGSPLITOP_SERIALIZE 0x04 /* apply serialfn to output */ #define AGGSPLITOP_DESERIALIZE 0x08 /* apply deserialfn to input */ /* Supported operating modes (i.e., useful combinations of these options): */ typedef enum AggSplit { /* Basic, non-split aggregation: */ AGGSPLIT_SIMPLE = 0, /* Initial phase of partial aggregation, with serialization: */ AGGSPLIT_INITIAL_SERIAL = AGGSPLITOP_SKIPFINAL | AGGSPLITOP_SERIALIZE, /* Final phase of partial aggregation, with deserialization: */ AGGSPLIT_FINAL_DESERIAL = AGGSPLITOP_COMBINE | AGGSPLITOP_DESERIALIZE } AggSplit; /* Test whether an AggSplit value selects each primitive option: */ #define DO_AGGSPLIT_COMBINE(as) (((as) & AGGSPLITOP_COMBINE) != 0) #define DO_AGGSPLIT_SKIPFINAL(as) (((as) & AGGSPLITOP_SKIPFINAL) != 0) #define DO_AGGSPLIT_SERIALIZE(as) (((as) & AGGSPLITOP_SERIALIZE) != 0) #define DO_AGGSPLIT_DESERIALIZE(as) (((as) & AGGSPLITOP_DESERIALIZE) != 0) /* * SetOpCmd and SetOpStrategy - * overall semantics and execution strategies for SetOp plan nodes * * This is needed in both pathnodes.h and plannodes.h, so put it here... */ typedef enum SetOpCmd { SETOPCMD_INTERSECT, SETOPCMD_INTERSECT_ALL, SETOPCMD_EXCEPT, SETOPCMD_EXCEPT_ALL } SetOpCmd; typedef enum SetOpStrategy { SETOP_SORTED, /* input must be sorted */ SETOP_HASHED /* use internal hashtable */ } SetOpStrategy; /* * OnConflictAction - * "ON CONFLICT" clause type of query * * This is needed in both parsenodes.h and plannodes.h, so put it here... */ typedef enum OnConflictAction { ONCONFLICT_NONE, /* No "ON CONFLICT" clause */ ONCONFLICT_NOTHING, /* ON CONFLICT ... DO NOTHING */ ONCONFLICT_UPDATE /* ON CONFLICT ... DO UPDATE */ } OnConflictAction; /* * LimitOption - * LIMIT option of query * * This is needed in both parsenodes.h and plannodes.h, so put it here... */ typedef enum LimitOption { LIMIT_OPTION_COUNT, /* FETCH FIRST... ONLY */ LIMIT_OPTION_WITH_TIES, /* FETCH FIRST... WITH TIES */ LIMIT_OPTION_DEFAULT, /* No limit present */ } LimitOption; #endif /* NODES_H */ /*------------------------------------------------------------------------- * * postgres_ext.h * * This file contains declarations of things that are visible everywhere * in PostgreSQL *and* are visible to clients of frontend interface libraries. * For example, the Oid type is part of the API of libpq and other libraries. * * Declarations which are specific to a particular interface should * go in the header file for that interface (such as libpq-fe.h). This * file is only for fundamental Postgres declarations. * * User-written C functions don't count as "external to Postgres." * Those function much as local modifications to the backend itself, and * use header files that are otherwise internal to Postgres to interface * with the backend. * * src/include/postgres_ext.h * *------------------------------------------------------------------------- */ #ifndef POSTGRES_EXT_H #define POSTGRES_EXT_H /* * Object ID is a fundamental type in Postgres. */ typedef unsigned int Oid; #ifdef __cplusplus #define InvalidOid (Oid(0)) #else #define InvalidOid ((Oid) 0) #endif #define OID_MAX UINT_MAX /* you will need to include <limits.h> to use the above #define */ #define atooid(x) ((Oid) strtoul((x), NULL, 10)) /* the above needs <stdlib.h> */ /* * Identifiers of error message fields. Kept here to keep common * between frontend and backend, and also to export them to libpq * applications. */ #define PG_DIAG_SEVERITY 'S' #define PG_DIAG_SEVERITY_NONLOCALIZED 'V' #define PG_DIAG_SQLSTATE 'C' #define PG_DIAG_MESSAGE_PRIMARY 'M' #define PG_DIAG_MESSAGE_DETAIL 'D' #define PG_DIAG_MESSAGE_HINT 'H' #define PG_DIAG_STATEMENT_POSITION 'P' #define PG_DIAG_INTERNAL_POSITION 'p' #define PG_DIAG_INTERNAL_QUERY 'q' #define PG_DIAG_CONTEXT 'W' #define PG_DIAG_SCHEMA_NAME 's' #define PG_DIAG_TABLE_NAME 't' #define PG_DIAG_COLUMN_NAME 'c' #define PG_DIAG_DATATYPE_NAME 'd' #define PG_DIAG_CONSTRAINT_NAME 'n' #define PG_DIAG_SOURCE_FILE 'F' #define PG_DIAG_SOURCE_LINE 'L' #define PG_DIAG_SOURCE_FUNCTION 'R' #endif /* POSTGRES_EXT_H */ /*------------------------------------------------------------------------- * * c.h * Fundamental C definitions. This is included by every .c file in * PostgreSQL (via either postgres.h or postgres_fe.h, as appropriate). * * Note that the definitions here are not intended to be exposed to clients * of the frontend interface libraries --- so we don't worry much about * polluting the namespace with lots of stuff... * * * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/c.h * *------------------------------------------------------------------------- */ /* *---------------------------------------------------------------- * TABLE OF CONTENTS * * When adding stuff to this file, please try to put stuff * into the relevant section, or add new sections as appropriate. * * section description * ------- ------------------------------------------------ * 0) pg_config.h and standard system headers * 1) compiler characteristics * 2) bool, true, false * 3) standard system types * 4) IsValid macros for system types * 5) lengthof, alignment * 6) assertions * 7) widely useful macros * 8) random stuff * 9) system-specific hacks * * NOTE: since this file is included by both frontend and backend modules, * it's usually wrong to put an "extern" declaration here, unless it's * ifdef'd so that it's seen in only one case or the other. * typedefs and macros are the kind of thing that might go here. * *---------------------------------------------------------------- */ #ifndef C_H #define C_H /* System header files that should be available everywhere in Postgres */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stddef.h> #include <stdarg.h> #ifdef HAVE_STRINGS_H #include <strings.h> #endif #include <stdint.h> #include <sys/types.h> #include <errno.h> #if defined(WIN32) || defined(__CYGWIN__) #include <fcntl.h> /* ensure O_BINARY is available */ #endif #include <locale.h> #ifdef ENABLE_NLS #include <libintl.h> #endif /* Define before including zlib.h to add const decorations to zlib API. */ #ifdef HAVE_LIBZ #define ZLIB_CONST #endif /* ---------------------------------------------------------------- * Section 1: compiler characteristics * * type prefixes (const, signed, volatile, inline) are handled in pg_config.h. * ---------------------------------------------------------------- */ /* * Disable "inline" if PG_FORCE_DISABLE_INLINE is defined. * This is used to work around compiler bugs and might also be useful for * investigatory purposes. */ #ifdef PG_FORCE_DISABLE_INLINE #undef inline #define inline #endif /* * Attribute macros * * GCC: https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html * GCC: https://gcc.gnu.org/onlinedocs/gcc/Type-Attributes.html * Clang: https://clang.llvm.org/docs/AttributeReference.html * Sunpro: https://docs.oracle.com/cd/E18659_01/html/821-1384/gjzke.html * XLC: https://www.ibm.com/support/knowledgecenter/SSGH2K_13.1.2/com.ibm.xlc131.aix.doc/language_ref/function_attributes.html * XLC: https://www.ibm.com/support/knowledgecenter/SSGH2K_13.1.2/com.ibm.xlc131.aix.doc/language_ref/type_attrib.html */ /* * For compilers which don't support __has_attribute, we just define * __has_attribute(x) to 0 so that we can define macros for various * __attribute__s more easily below. */ #ifndef __has_attribute #define __has_attribute(attribute) 0 #endif /* only GCC supports the unused attribute */ #ifdef __GNUC__ #define pg_attribute_unused() __attribute__((unused)) #else #define pg_attribute_unused() #endif /* * pg_nodiscard means the compiler should warn if the result of a function * call is ignored. The name "nodiscard" is chosen in alignment with * (possibly future) C and C++ standards. For maximum compatibility, use it * as a function declaration specifier, so it goes before the return type. */ #ifdef __GNUC__ #define pg_nodiscard __attribute__((warn_unused_result)) #else #define pg_nodiscard #endif /* * Place this macro before functions that should be allowed to make misaligned * accesses. Think twice before using it on non-x86-specific code! * Testing can be done with "-fsanitize=alignment -fsanitize-trap=alignment" * on clang, or "-fsanitize=alignment -fno-sanitize-recover=alignment" on gcc. */ #if __clang_major__ >= 7 || __GNUC__ >= 8 #define pg_attribute_no_sanitize_alignment() __attribute__((no_sanitize("alignment"))) #else #define pg_attribute_no_sanitize_alignment() #endif /* * pg_attribute_nonnull means the compiler should warn if the function is * called with the listed arguments set to NULL. If no arguments are * listed, the compiler should warn if any pointer arguments are set to NULL. */ #if __has_attribute (nonnull) #define pg_attribute_nonnull(...) __attribute__((nonnull(__VA_ARGS__))) #else #define pg_attribute_nonnull(...) #endif /* * Append PG_USED_FOR_ASSERTS_ONLY to definitions of variables that are only * used in assert-enabled builds, to avoid compiler warnings about unused * variables in assert-disabled builds. */ #ifdef USE_ASSERT_CHECKING #define PG_USED_FOR_ASSERTS_ONLY #else #define PG_USED_FOR_ASSERTS_ONLY pg_attribute_unused() #endif /* GCC and XLC support format attributes */ #if defined(__GNUC__) || defined(__IBMC__) #define pg_attribute_format_arg(a) __attribute__((format_arg(a))) #define pg_attribute_printf(f,a) __attribute__((format(PG_PRINTF_ATTRIBUTE, f, a))) #else #define pg_attribute_format_arg(a) #define pg_attribute_printf(f,a) #endif /* GCC, Sunpro and XLC support aligned, packed and noreturn */ #if defined(__GNUC__) || defined(__SUNPRO_C) || defined(__IBMC__) #define pg_attribute_aligned(a) __attribute__((aligned(a))) #define pg_attribute_noreturn() __attribute__((noreturn)) #define pg_attribute_packed() __attribute__((packed)) #define HAVE_PG_ATTRIBUTE_NORETURN 1 #elif defined(_MSC_VER) /* * MSVC supports aligned. noreturn is also possible but in MSVC it is * declared before the definition while pg_attribute_noreturn() macro * is currently used after the definition. * * Packing is also possible but only by wrapping the entire struct definition * which doesn't fit into our current macro declarations. */ #define pg_attribute_aligned(a) __declspec(align(a)) #define pg_attribute_noreturn() #else /* * NB: aligned and packed are not given default definitions because they * affect code functionality; they *must* be implemented by the compiler * if they are to be used. */ #define pg_attribute_noreturn() #endif /* * Use "pg_attribute_always_inline" in place of "inline" for functions that * we wish to force inlining of, even when the compiler's heuristics would * choose not to. But, if possible, don't force inlining in unoptimized * debug builds. */ #if (defined(__GNUC__) && __GNUC__ > 3 && defined(__OPTIMIZE__)) || defined(__SUNPRO_C) || defined(__IBMC__) /* GCC > 3, Sunpro and XLC support always_inline via __attribute__ */ #define pg_attribute_always_inline __attribute__((always_inline)) inline #elif defined(_MSC_VER) /* MSVC has a special keyword for this */ #define pg_attribute_always_inline __forceinline #else /* Otherwise, the best we can do is to say "inline" */ #define pg_attribute_always_inline inline #endif /* * Forcing a function not to be inlined can be useful if it's the slow path of * a performance-critical function, or should be visible in profiles to allow * for proper cost attribution. Note that unlike the pg_attribute_XXX macros * above, this should be placed before the function's return type and name. */ /* GCC, Sunpro and XLC support noinline via __attribute__ */ #if (defined(__GNUC__) && __GNUC__ > 2) || defined(__SUNPRO_C) || defined(__IBMC__) #define pg_noinline __attribute__((noinline)) /* msvc via declspec */ #elif defined(_MSC_VER) #define pg_noinline __declspec(noinline) #else #define pg_noinline #endif /* * For now, just define pg_attribute_cold and pg_attribute_hot to be empty * macros on minGW 8.1. There appears to be a compiler bug that results in * compilation failure. At this time, we still have at least one buildfarm * animal running that compiler, so this should make that green again. It's * likely this compiler is not popular enough to warrant keeping this code * around forever, so let's just remove it once the last buildfarm animal * upgrades. */ #if defined(__MINGW64__) && __GNUC__ == 8 && __GNUC_MINOR__ == 1 #define pg_attribute_cold #define pg_attribute_hot #else /* * Marking certain functions as "hot" or "cold" can be useful to assist the * compiler in arranging the assembly code in a more efficient way. */ #if __has_attribute (cold) #define pg_attribute_cold __attribute__((cold)) #else #define pg_attribute_cold #endif #if __has_attribute (hot) #define pg_attribute_hot __attribute__((hot)) #else #define pg_attribute_hot #endif #endif /* defined(__MINGW64__) && __GNUC__ == 8 && * __GNUC_MINOR__ == 1 */ /* * Mark a point as unreachable in a portable fashion. This should preferably * be something that the compiler understands, to aid code generation. * In assert-enabled builds, we prefer abort() for debugging reasons. */ #if defined(HAVE__BUILTIN_UNREACHABLE) && !defined(USE_ASSERT_CHECKING) #define pg_unreachable() __builtin_unreachable() #elif defined(_MSC_VER) && !defined(USE_ASSERT_CHECKING) #define pg_unreachable() __assume(0) #else #define pg_unreachable() abort() #endif /* * Hints to the compiler about the likelihood of a branch. Both likely() and * unlikely() return the boolean value of the contained expression. * * These should only be used sparingly, in very hot code paths. It's very easy * to mis-estimate likelihoods. */ #if __GNUC__ >= 3 #define likely(x) __builtin_expect((x) != 0, 1) #define unlikely(x) __builtin_expect((x) != 0, 0) #else #define likely(x) ((x) != 0) #define unlikely(x) ((x) != 0) #endif /* * CppAsString * Convert the argument to a string, using the C preprocessor. * CppAsString2 * Convert the argument to a string, after one round of macro expansion. * CppConcat * Concatenate two arguments together, using the C preprocessor. * * Note: There used to be support here for pre-ANSI C compilers that didn't * support # and ##. Nowadays, these macros are just for clarity and/or * backward compatibility with existing PostgreSQL code. */ #define CppAsString(identifier) #identifier #define CppAsString2(x) CppAsString(x) #define CppConcat(x, y) x##y /* * VA_ARGS_NARGS * Returns the number of macro arguments it is passed. * * An empty argument still counts as an argument, so effectively, this is * "one more than the number of commas in the argument list". * * This works for up to 63 arguments. Internally, VA_ARGS_NARGS_() is passed * 64+N arguments, and the C99 standard only requires macros to allow up to * 127 arguments, so we can't portably go higher. The implementation is * pretty trivial: VA_ARGS_NARGS_() returns its 64th argument, and we set up * the call so that that is the appropriate one of the list of constants. * This idea is due to Laurent Deniau. * * MSVC has an implementation of __VA_ARGS__ that doesn't conform to the * standard unless you use the /Zc:preprocessor compiler flag, but that * isn't available before Visual Studio 2019. For now, use a different * definition that also works on older compilers. */ #ifdef _MSC_VER #define EXPAND(args) args #define VA_ARGS_NARGS(...) \ VA_ARGS_NARGS_ EXPAND((__VA_ARGS__, \ 63,62,61,60, \ 59,58,57,56,55,54,53,52,51,50, \ 49,48,47,46,45,44,43,42,41,40, \ 39,38,37,36,35,34,33,32,31,30, \ 29,28,27,26,25,24,23,22,21,20, \ 19,18,17,16,15,14,13,12,11,10, \ 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)) #else #define VA_ARGS_NARGS(...) \ VA_ARGS_NARGS_(__VA_ARGS__, \ 63,62,61,60, \ 59,58,57,56,55,54,53,52,51,50, \ 49,48,47,46,45,44,43,42,41,40, \ 39,38,37,36,35,34,33,32,31,30, \ 29,28,27,26,25,24,23,22,21,20, \ 19,18,17,16,15,14,13,12,11,10, \ 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) #endif #define VA_ARGS_NARGS_( \ _01,_02,_03,_04,_05,_06,_07,_08,_09,_10, \ _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \ _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \ _31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \ _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \ _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \ _61,_62,_63, N, ...) \ (N) /* * Generic function pointer. This can be used in the rare cases where it's * necessary to cast a function pointer to a seemingly incompatible function * pointer type while avoiding gcc's -Wcast-function-type warnings. */ typedef void (*pg_funcptr_t) (void); /* * We require C99, hence the compiler should understand flexible array * members. However, for documentation purposes we still consider it to be * project style to write "field[FLEXIBLE_ARRAY_MEMBER]" not just "field[]". * When computing the size of such an object, use "offsetof(struct s, f)" * for portability. Don't use "offsetof(struct s, f[0])", as this doesn't * work with MSVC and with C++ compilers. */ #define FLEXIBLE_ARRAY_MEMBER /* empty */ /* * Does the compiler support #pragma GCC system_header? We optionally use it * to avoid warnings that we can't fix (e.g. in the perl headers). * See https://gcc.gnu.org/onlinedocs/cpp/System-Headers.html * * Headers for which we do not want to show compiler warnings can, * conditionally, use #pragma GCC system_header to avoid warnings. Obviously * this should only be used for external headers over which we do not have * control. * * Support for the pragma is tested here, instead of during configure, as gcc * also warns about the pragma being used in a .c file. It's surprisingly hard * to get autoconf to use .h as the file-ending. Looks like gcc has * implemented the pragma since the 2000, so this test should suffice. * * * Alternatively, we could add the include paths for problematic headers with * -isystem, but that is a larger hammer and is harder to search for. * * A more granular alternative would be to use #pragma GCC diagnostic * push/ignored/pop, but gcc warns about unknown warnings being ignored, so * every to-be-ignored-temporarily compiler warning would require its own * pg_config.h symbol and #ifdef. */ #ifdef __GNUC__ #define HAVE_PRAGMA_GCC_SYSTEM_HEADER 1 #endif /* ---------------------------------------------------------------- * Section 2: bool, true, false * ---------------------------------------------------------------- */ /* * bool * Boolean value, either true or false. * * We use stdbool.h if available and its bool has size 1. That's useful for * better compiler and debugger output and for compatibility with third-party * libraries. But PostgreSQL currently cannot deal with bool of other sizes; * there are static assertions around the code to prevent that. * * For C++ compilers, we assume the compiler has a compatible built-in * definition of bool. * * See also the version of this code in src/interfaces/ecpg/include/ecpglib.h. */ #ifndef __cplusplus #ifdef PG_USE_STDBOOL #include <stdbool.h> #else #ifndef bool typedef unsigned char bool; #endif #ifndef true #define true ((bool) 1) #endif #ifndef false #define false ((bool) 0) #endif #endif /* not PG_USE_STDBOOL */ #endif /* not C++ */ /* ---------------------------------------------------------------- * Section 3: standard system types * ---------------------------------------------------------------- */ /* * Pointer * Variable holding address of any memory resident object. * * XXX Pointer arithmetic is done with this, so it can't be void * * under "true" ANSI compilers. */ typedef char *Pointer; /* * intN * Signed integer, EXACTLY N BITS IN SIZE, * used for numerical computations and the * frontend/backend protocol. */ #ifndef HAVE_INT8 typedef signed char int8; /* == 8 bits */ typedef signed short int16; /* == 16 bits */ typedef signed int int32; /* == 32 bits */ #endif /* not HAVE_INT8 */ /* * uintN * Unsigned integer, EXACTLY N BITS IN SIZE, * used for numerical computations and the * frontend/backend protocol. */ #ifndef HAVE_UINT8 typedef unsigned char uint8; /* == 8 bits */ typedef unsigned short uint16; /* == 16 bits */ typedef unsigned int uint32; /* == 32 bits */ #endif /* not HAVE_UINT8 */ /* * bitsN * Unit of bitwise operation, AT LEAST N BITS IN SIZE. */ typedef uint8 bits8; /* >= 8 bits */ typedef uint16 bits16; /* >= 16 bits */ typedef uint32 bits32; /* >= 32 bits */ /* * 64-bit integers */ typedef long long int int64; typedef unsigned long long int uint64; #define INT64CONST(x) (x##LL) #define UINT64CONST(x) (x##ULL) /* snprintf format strings to use for 64-bit integers */ #define INT64_FORMAT "%" INT64_MODIFIER "d" #define UINT64_FORMAT "%" INT64_MODIFIER "u" /* * 128-bit signed and unsigned integers * There currently is only limited support for such types. * E.g. 128bit literals and snprintf are not supported; but math is. * Also, because we exclude such types when choosing MAXIMUM_ALIGNOF, * it must be possible to coerce the compiler to allocate them on no * more than MAXALIGN boundaries. */ #if defined(PG_INT128_TYPE) #if defined(pg_attribute_aligned) || ALIGNOF_PG_INT128_TYPE <= MAXIMUM_ALIGNOF #define HAVE_INT128 1 typedef PG_INT128_TYPE int128 #if defined(pg_attribute_aligned) pg_attribute_aligned(MAXIMUM_ALIGNOF) #endif ; typedef unsigned PG_INT128_TYPE uint128 #if defined(pg_attribute_aligned) pg_attribute_aligned(MAXIMUM_ALIGNOF) #endif ; #endif #endif /* * stdint.h limits aren't guaranteed to have compatible types with our fixed * width types. So just define our own. */ #define PG_INT8_MIN (-0x7F-1) #define PG_INT8_MAX (0x7F) #define PG_UINT8_MAX (0xFF) #define PG_INT16_MIN (-0x7FFF-1) #define PG_INT16_MAX (0x7FFF) #define PG_UINT16_MAX (0xFFFF) #define PG_INT32_MIN (-0x7FFFFFFF-1) #define PG_INT32_MAX (0x7FFFFFFF) #define PG_UINT32_MAX (0xFFFFFFFFU) #define PG_INT64_MIN (-INT64CONST(0x7FFFFFFFFFFFFFFF) - 1) #define PG_INT64_MAX INT64CONST(0x7FFFFFFFFFFFFFFF) #define PG_UINT64_MAX UINT64CONST(0xFFFFFFFFFFFFFFFF) /* * We now always use int64 timestamps, but keep this symbol defined for the * benefit of external code that might test it. */ #define HAVE_INT64_TIMESTAMP /* * Size * Size of any memory resident object, as returned by sizeof. */ typedef size_t Size; /* * Index * Index into any memory resident array. * * Note: * Indices are non negative. */ typedef unsigned int Index; /* * Offset * Offset into any memory resident array. * * Note: * This differs from an Index in that an Index is always * non negative, whereas Offset may be negative. */ typedef signed int Offset; /* * Common Postgres datatype names (as used in the catalogs) */ typedef float float4; typedef double float8; #ifdef USE_FLOAT8_BYVAL #define FLOAT8PASSBYVAL true #else #define FLOAT8PASSBYVAL false #endif /* * Oid, RegProcedure, TransactionId, SubTransactionId, MultiXactId, * CommandId */ /* typedef Oid is in postgres_ext.h */ /* * regproc is the type name used in the include/catalog headers, but * RegProcedure is the preferred name in C code. */ typedef Oid regproc; typedef regproc RegProcedure; typedef uint32 TransactionId; typedef uint32 LocalTransactionId; typedef uint32 SubTransactionId; #define InvalidSubTransactionId ((SubTransactionId) 0) #define TopSubTransactionId ((SubTransactionId) 1) /* MultiXactId must be equivalent to TransactionId, to fit in t_xmax */ typedef TransactionId MultiXactId; typedef uint32 MultiXactOffset; typedef uint32 CommandId; #define FirstCommandId ((CommandId) 0) #define InvalidCommandId (~(CommandId)0) /* ---------------- * Variable-length datatypes all share the 'struct varlena' header. * * NOTE: for TOASTable types, this is an oversimplification, since the value * may be compressed or moved out-of-line. However datatype-specific routines * are mostly content to deal with de-TOASTed values only, and of course * client-side routines should never see a TOASTed value. But even in a * de-TOASTed value, beware of touching vl_len_ directly, as its * representation is no longer convenient. It's recommended that code always * use macros VARDATA_ANY, VARSIZE_ANY, VARSIZE_ANY_EXHDR, VARDATA, VARSIZE, * and SET_VARSIZE instead of relying on direct mentions of the struct fields. * See postgres.h for details of the TOASTed form. * ---------------- */ struct varlena { char vl_len_[4]; /* Do not touch this field directly! */ char vl_dat[FLEXIBLE_ARRAY_MEMBER]; /* Data content is here */ }; #define VARHDRSZ ((int32) sizeof(int32)) /* * These widely-used datatypes are just a varlena header and the data bytes. * There is no terminating null or anything like that --- the data length is * always VARSIZE_ANY_EXHDR(ptr). */ typedef struct varlena bytea; typedef struct varlena text; typedef struct varlena BpChar; /* blank-padded char, ie SQL char(n) */ typedef struct varlena VarChar; /* var-length char, ie SQL varchar(n) */ /* * Specialized array types. These are physically laid out just the same * as regular arrays (so that the regular array subscripting code works * with them). They exist as distinct types mostly for historical reasons: * they have nonstandard I/O behavior which we don't want to change for fear * of breaking applications that look at the system catalogs. There is also * an implementation issue for oidvector: it's part of the primary key for * pg_proc, and we can't use the normal btree array support routines for that * without circularity. */ typedef struct { int32 vl_len_; /* these fields must match ArrayType! */ int ndim; /* always 1 for int2vector */ int32 dataoffset; /* always 0 for int2vector */ Oid elemtype; int dim1; int lbound1; int16 values[FLEXIBLE_ARRAY_MEMBER]; } int2vector; typedef struct { int32 vl_len_; /* these fields must match ArrayType! */ int ndim; /* always 1 for oidvector */ int32 dataoffset; /* always 0 for oidvector */ Oid elemtype; int dim1; int lbound1; Oid values[FLEXIBLE_ARRAY_MEMBER]; } oidvector; #define NameStr(name) ((name).data) /* ---------------------------------------------------------------- * Section 4: IsValid macros for system types * ---------------------------------------------------------------- */ /* * BoolIsValid * True iff bool is valid. */ #define BoolIsValid(boolean) ((boolean) == false || (boolean) == true) /* * PointerIsValid * True iff pointer is valid. */ #define PointerIsValid(pointer) ((const void*)(pointer) != NULL) /* * PointerIsAligned * True iff pointer is properly aligned to point to the given type. */ #define PointerIsAligned(pointer, type) \ (((uintptr_t)(pointer) % (sizeof (type))) == 0) #define OffsetToPointer(base, offset) \ ((void *)((char *) base + offset)) #define OidIsValid(objectId) ((bool) ((objectId) != InvalidOid)) #define RegProcedureIsValid(p) OidIsValid(p) /* ---------------------------------------------------------------- * Section 5: lengthof, alignment * ---------------------------------------------------------------- */ /* * lengthof * Number of elements in an array. */ #define lengthof(array) (sizeof (array) / sizeof ((array)[0])) /* ---------------- * Alignment macros: align a length or address appropriately for a given type. * The fooALIGN() macros round up to a multiple of the required alignment, * while the fooALIGN_DOWN() macros round down. The latter are more useful * for problems like "how many X-sized structures will fit in a page?". * * NOTE: TYPEALIGN[_DOWN] will not work if ALIGNVAL is not a power of 2. * That case seems extremely unlikely to be needed in practice, however. * * NOTE: MAXIMUM_ALIGNOF, and hence MAXALIGN(), intentionally exclude any * larger-than-8-byte types the compiler might have. * ---------------- */ #define TYPEALIGN(ALIGNVAL,LEN) \ (((uintptr_t) (LEN) + ((ALIGNVAL) - 1)) & ~((uintptr_t) ((ALIGNVAL) - 1))) #define SHORTALIGN(LEN) TYPEALIGN(ALIGNOF_SHORT, (LEN)) #define INTALIGN(LEN) TYPEALIGN(ALIGNOF_INT, (LEN)) #define LONGALIGN(LEN) TYPEALIGN(ALIGNOF_LONG, (LEN)) #define DOUBLEALIGN(LEN) TYPEALIGN(ALIGNOF_DOUBLE, (LEN)) #define MAXALIGN(LEN) TYPEALIGN(MAXIMUM_ALIGNOF, (LEN)) /* MAXALIGN covers only built-in types, not buffers */ #define BUFFERALIGN(LEN) TYPEALIGN(ALIGNOF_BUFFER, (LEN)) #define CACHELINEALIGN(LEN) TYPEALIGN(PG_CACHE_LINE_SIZE, (LEN)) #define TYPEALIGN_DOWN(ALIGNVAL,LEN) \ (((uintptr_t) (LEN)) & ~((uintptr_t) ((ALIGNVAL) - 1))) #define SHORTALIGN_DOWN(LEN) TYPEALIGN_DOWN(ALIGNOF_SHORT, (LEN)) #define INTALIGN_DOWN(LEN) TYPEALIGN_DOWN(ALIGNOF_INT, (LEN)) #define LONGALIGN_DOWN(LEN) TYPEALIGN_DOWN(ALIGNOF_LONG, (LEN)) #define DOUBLEALIGN_DOWN(LEN) TYPEALIGN_DOWN(ALIGNOF_DOUBLE, (LEN)) #define MAXALIGN_DOWN(LEN) TYPEALIGN_DOWN(MAXIMUM_ALIGNOF, (LEN)) #define BUFFERALIGN_DOWN(LEN) TYPEALIGN_DOWN(ALIGNOF_BUFFER, (LEN)) /* * The above macros will not work with types wider than uintptr_t, like with * uint64 on 32-bit platforms. That's not problem for the usual use where a * pointer or a length is aligned, but for the odd case that you need to * align something (potentially) wider, use TYPEALIGN64. */ #define TYPEALIGN64(ALIGNVAL,LEN) \ (((uint64) (LEN) + ((ALIGNVAL) - 1)) & ~((uint64) ((ALIGNVAL) - 1))) /* we don't currently need wider versions of the other ALIGN macros */ #define MAXALIGN64(LEN) TYPEALIGN64(MAXIMUM_ALIGNOF, (LEN)) /* ---------------------------------------------------------------- * Section 6: assertions * ---------------------------------------------------------------- */ /* * USE_ASSERT_CHECKING, if defined, turns on all the assertions. * - plai 9/5/90 * * It should _NOT_ be defined in releases or in benchmark copies */ /* * Assert() can be used in both frontend and backend code. In frontend code it * just calls the standard assert, if it's available. If use of assertions is * not configured, it does nothing. */ #ifndef USE_ASSERT_CHECKING #define Assert(condition) ((void)true) #define AssertMacro(condition) ((void)true) #elif defined(FRONTEND) #include <assert.h> #define Assert(p) assert(p) #define AssertMacro(p) ((void) assert(p)) #else /* USE_ASSERT_CHECKING && !FRONTEND */ /* * Assert * Generates a fatal exception if the given condition is false. */ #define Assert(condition) \ do { \ if (!(condition)) \ ExceptionalCondition(#condition, __FILE__, __LINE__); \ } while (0) /* * AssertMacro is the same as Assert but it's suitable for use in * expression-like macros, for example: * * #define foo(x) (AssertMacro(x != 0), bar(x)) */ #define AssertMacro(condition) \ ((void) ((condition) || \ (ExceptionalCondition(#condition, __FILE__, __LINE__), 0))) #endif /* USE_ASSERT_CHECKING && !FRONTEND */ /* * Check that `ptr' is `bndr' aligned. */ #define AssertPointerAlignment(ptr, bndr) \ Assert(TYPEALIGN(bndr, (uintptr_t)(ptr)) == (uintptr_t)(ptr)) /* * ExceptionalCondition is compiled into the backend whether or not * USE_ASSERT_CHECKING is defined, so as to support use of extensions * that are built with that #define with a backend that isn't. Hence, * we should declare it as long as !FRONTEND. */ #ifndef FRONTEND extern void ExceptionalCondition(const char *conditionName, const char *fileName, int lineNumber) pg_attribute_noreturn(); #endif /* * Macros to support compile-time assertion checks. * * If the "condition" (a compile-time-constant expression) evaluates to false, * throw a compile error using the "errmessage" (a string literal). * * C11 has _Static_assert(), and most C99 compilers already support that. For * portability, we wrap it into StaticAssertDecl(). _Static_assert() is a * "declaration", and so it must be placed where for example a variable * declaration would be valid. As long as we compile with * -Wno-declaration-after-statement, that also means it cannot be placed after * statements in a function. Macros StaticAssertStmt() and StaticAssertExpr() * make it safe to use as a statement or in an expression, respectively. * * For compilers without _Static_assert(), we fall back on a kluge that * assumes the compiler will complain about a negative width for a struct * bit-field. This will not include a helpful error message, but it beats not * getting an error at all. */ #ifndef __cplusplus #ifdef HAVE__STATIC_ASSERT #define StaticAssertDecl(condition, errmessage) \ _Static_assert(condition, errmessage) #define StaticAssertStmt(condition, errmessage) \ do { _Static_assert(condition, errmessage); } while(0) #define StaticAssertExpr(condition, errmessage) \ ((void) ({ StaticAssertStmt(condition, errmessage); true; })) #else /* !HAVE__STATIC_ASSERT */ #define StaticAssertDecl(condition, errmessage) \ extern void static_assert_func(int static_assert_failure[(condition) ? 1 : -1]) #define StaticAssertStmt(condition, errmessage) \ ((void) sizeof(struct { int static_assert_failure : (condition) ? 1 : -1; })) #define StaticAssertExpr(condition, errmessage) \ StaticAssertStmt(condition, errmessage) #endif /* HAVE__STATIC_ASSERT */ #else /* C++ */ #if defined(__cpp_static_assert) && __cpp_static_assert >= 200410 #define StaticAssertDecl(condition, errmessage) \ static_assert(condition, errmessage) #define StaticAssertStmt(condition, errmessage) \ static_assert(condition, errmessage) #define StaticAssertExpr(condition, errmessage) \ ({ static_assert(condition, errmessage); }) #else /* !__cpp_static_assert */ #define StaticAssertDecl(condition, errmessage) \ extern void static_assert_func(int static_assert_failure[(condition) ? 1 : -1]) #define StaticAssertStmt(condition, errmessage) \ do { struct static_assert_struct { int static_assert_failure : (condition) ? 1 : -1; }; } while(0) #define StaticAssertExpr(condition, errmessage) \ ((void) ({ StaticAssertStmt(condition, errmessage); })) #endif /* __cpp_static_assert */ #endif /* C++ */ /* * Compile-time checks that a variable (or expression) has the specified type. * * AssertVariableIsOfType() can be used as a statement. * AssertVariableIsOfTypeMacro() is intended for use in macros, eg * #define foo(x) (AssertVariableIsOfTypeMacro(x, int), bar(x)) * * If we don't have __builtin_types_compatible_p, we can still assert that * the types have the same size. This is far from ideal (especially on 32-bit * platforms) but it provides at least some coverage. */ #ifdef HAVE__BUILTIN_TYPES_COMPATIBLE_P #define AssertVariableIsOfType(varname, typename) \ StaticAssertStmt(__builtin_types_compatible_p(__typeof__(varname), typename), \ CppAsString(varname) " does not have type " CppAsString(typename)) #define AssertVariableIsOfTypeMacro(varname, typename) \ (StaticAssertExpr(__builtin_types_compatible_p(__typeof__(varname), typename), \ CppAsString(varname) " does not have type " CppAsString(typename))) #else /* !HAVE__BUILTIN_TYPES_COMPATIBLE_P */ #define AssertVariableIsOfType(varname, typename) \ StaticAssertStmt(sizeof(varname) == sizeof(typename), \ CppAsString(varname) " does not have type " CppAsString(typename)) #define AssertVariableIsOfTypeMacro(varname, typename) \ (StaticAssertExpr(sizeof(varname) == sizeof(typename), \ CppAsString(varname) " does not have type " CppAsString(typename))) #endif /* HAVE__BUILTIN_TYPES_COMPATIBLE_P */ /* ---------------------------------------------------------------- * Section 7: widely useful macros * ---------------------------------------------------------------- */ /* * Max * Return the maximum of two numbers. */ #define Max(x, y) ((x) > (y) ? (x) : (y)) /* * Min * Return the minimum of two numbers. */ #define Min(x, y) ((x) < (y) ? (x) : (y)) /* Get a bit mask of the bits set in non-long aligned addresses */ #define LONG_ALIGN_MASK (sizeof(long) - 1) /* * MemSet * Exactly the same as standard library function memset(), but considerably * faster for zeroing small word-aligned structures (such as parsetree nodes). * This has to be a macro because the main point is to avoid function-call * overhead. However, we have also found that the loop is faster than * native libc memset() on some platforms, even those with assembler * memset() functions. More research needs to be done, perhaps with * MEMSET_LOOP_LIMIT tests in configure. */ #define MemSet(start, val, len) \ do \ { \ /* must be void* because we don't know if it is integer aligned yet */ \ void *_vstart = (void *) (start); \ int _val = (val); \ Size _len = (len); \ \ if ((((uintptr_t) _vstart) & LONG_ALIGN_MASK) == 0 && \ (_len & LONG_ALIGN_MASK) == 0 && \ _val == 0 && \ _len <= MEMSET_LOOP_LIMIT && \ /* \ * If MEMSET_LOOP_LIMIT == 0, optimizer should find \ * the whole "if" false at compile time. \ */ \ MEMSET_LOOP_LIMIT != 0) \ { \ long *_start = (long *) _vstart; \ long *_stop = (long *) ((char *) _start + _len); \ while (_start < _stop) \ *_start++ = 0; \ } \ else \ memset(_vstart, _val, _len); \ } while (0) /* * MemSetAligned is the same as MemSet except it omits the test to see if * "start" is word-aligned. This is okay to use if the caller knows a-priori * that the pointer is suitably aligned (typically, because he just got it * from palloc(), which always delivers a max-aligned pointer). */ #define MemSetAligned(start, val, len) \ do \ { \ long *_start = (long *) (start); \ int _val = (val); \ Size _len = (len); \ \ if ((_len & LONG_ALIGN_MASK) == 0 && \ _val == 0 && \ _len <= MEMSET_LOOP_LIMIT && \ MEMSET_LOOP_LIMIT != 0) \ { \ long *_stop = (long *) ((char *) _start + _len); \ while (_start < _stop) \ *_start++ = 0; \ } \ else \ memset(_start, _val, _len); \ } while (0) /* * MemSetTest/MemSetLoop are a variant version that allow all the tests in * MemSet to be done at compile time in cases where "val" and "len" are * constants *and* we know the "start" pointer must be word-aligned. * If MemSetTest succeeds, then it is okay to use MemSetLoop, otherwise use * MemSetAligned. Beware of multiple evaluations of the arguments when using * this approach. */ #define MemSetTest(val, len) \ ( ((len) & LONG_ALIGN_MASK) == 0 && \ (len) <= MEMSET_LOOP_LIMIT && \ MEMSET_LOOP_LIMIT != 0 && \ (val) == 0 ) #define MemSetLoop(start, val, len) \ do \ { \ long * _start = (long *) (start); \ long * _stop = (long *) ((char *) _start + (Size) (len)); \ \ while (_start < _stop) \ *_start++ = 0; \ } while (0) /* * Macros for range-checking float values before converting to integer. * We must be careful here that the boundary values are expressed exactly * in the float domain. PG_INTnn_MIN is an exact power of 2, so it will * be represented exactly; but PG_INTnn_MAX isn't, and might get rounded * off, so avoid using that. * The input must be rounded to an integer beforehand, typically with rint(), * else we might draw the wrong conclusion about close-to-the-limit values. * These macros will do the right thing for Inf, but not necessarily for NaN, * so check isnan(num) first if that's a possibility. */ #define FLOAT4_FITS_IN_INT16(num) \ ((num) >= (float4) PG_INT16_MIN && (num) < -((float4) PG_INT16_MIN)) #define FLOAT4_FITS_IN_INT32(num) \ ((num) >= (float4) PG_INT32_MIN && (num) < -((float4) PG_INT32_MIN)) #define FLOAT4_FITS_IN_INT64(num) \ ((num) >= (float4) PG_INT64_MIN && (num) < -((float4) PG_INT64_MIN)) #define FLOAT8_FITS_IN_INT16(num) \ ((num) >= (float8) PG_INT16_MIN && (num) < -((float8) PG_INT16_MIN)) #define FLOAT8_FITS_IN_INT32(num) \ ((num) >= (float8) PG_INT32_MIN && (num) < -((float8) PG_INT32_MIN)) #define FLOAT8_FITS_IN_INT64(num) \ ((num) >= (float8) PG_INT64_MIN && (num) < -((float8) PG_INT64_MIN)) /* ---------------------------------------------------------------- * Section 8: random stuff * ---------------------------------------------------------------- */ /* * Invert the sign of a qsort-style comparison result, ie, exchange negative * and positive integer values, being careful not to get the wrong answer * for INT_MIN. The argument should be an integral variable. */ #define INVERT_COMPARE_RESULT(var) \ ((var) = ((var) < 0) ? 1 : -(var)) /* msb for char */ #define HIGHBIT (0x80) #define IS_HIGHBIT_SET(ch) ((unsigned char)(ch) & HIGHBIT) /* * Support macros for escaping strings. escape_backslash should be true * if generating a non-standard-conforming string. Prefixing a string * with ESCAPE_STRING_SYNTAX guarantees it is non-standard-conforming. * Beware of multiple evaluation of the "ch" argument! */ #define SQL_STR_DOUBLE(ch, escape_backslash) \ ((ch) == '\'' || ((ch) == '\\' && (escape_backslash))) #define ESCAPE_STRING_SYNTAX 'E' #define STATUS_OK (0) #define STATUS_ERROR (-1) #define STATUS_EOF (-2) /* * gettext support */ #ifndef ENABLE_NLS /* stuff we'd otherwise get from <libintl.h> */ #define gettext(x) (x) #define dgettext(d,x) (x) #define ngettext(s,p,n) ((n) == 1 ? (s) : (p)) #define dngettext(d,s,p,n) ((n) == 1 ? (s) : (p)) #endif #define _(x) gettext(x) /* * Use this to mark string constants as needing translation at some later * time, rather than immediately. This is useful for cases where you need * access to the original string and translated string, and for cases where * immediate translation is not possible, like when initializing global * variables. * * https://www.gnu.org/software/gettext/manual/html_node/Special-cases.html */ #define gettext_noop(x) (x) /* * To better support parallel installations of major PostgreSQL * versions as well as parallel installations of major library soname * versions, we mangle the gettext domain name by appending those * version numbers. The coding rule ought to be that wherever the * domain name is mentioned as a literal, it must be wrapped into * PG_TEXTDOMAIN(). The macros below do not work on non-literals; but * that is somewhat intentional because it avoids having to worry * about multiple states of premangling and postmangling as the values * are being passed around. * * Make sure this matches the installation rules in nls-global.mk. */ #ifdef SO_MAJOR_VERSION #define PG_TEXTDOMAIN(domain) (domain CppAsString2(SO_MAJOR_VERSION) "-" PG_MAJORVERSION) #else #define PG_TEXTDOMAIN(domain) (domain "-" PG_MAJORVERSION) #endif /* * Macro that allows to cast constness and volatile away from an expression, but doesn't * allow changing the underlying type. Enforcement of the latter * currently only works for gcc like compilers. * * Please note IT IS NOT SAFE to cast constness away if the result will ever * be modified (it would be undefined behaviour). Doing so anyway can cause * compiler misoptimizations or runtime crashes (modifying readonly memory). * It is only safe to use when the result will not be modified, but API * design or language restrictions prevent you from declaring that * (e.g. because a function returns both const and non-const variables). * * Note that this only works in function scope, not for global variables (it'd * be nice, but not trivial, to improve that). */ #if defined(__cplusplus) #define unconstify(underlying_type, expr) const_cast<underlying_type>(expr) #define unvolatize(underlying_type, expr) const_cast<underlying_type>(expr) #elif defined(HAVE__BUILTIN_TYPES_COMPATIBLE_P) #define unconstify(underlying_type, expr) \ (StaticAssertExpr(__builtin_types_compatible_p(__typeof(expr), const underlying_type), \ "wrong cast"), \ (underlying_type) (expr)) #define unvolatize(underlying_type, expr) \ (StaticAssertExpr(__builtin_types_compatible_p(__typeof(expr), volatile underlying_type), \ "wrong cast"), \ (underlying_type) (expr)) #else #define unconstify(underlying_type, expr) \ ((underlying_type) (expr)) #define unvolatize(underlying_type, expr) \ ((underlying_type) (expr)) #endif /* ---------------------------------------------------------------- * Section 9: system-specific hacks * * This should be limited to things that absolutely have to be * included in every source file. The port-specific header file * is usually a better place for this sort of thing. * ---------------------------------------------------------------- */ /* * NOTE: this is also used for opening text files. * WIN32 treats Control-Z as EOF in files opened in text mode. * Therefore, we open files in binary mode on Win32 so we can read * literal control-Z. The other affect is that we see CRLF, but * that is OK because we can already handle those cleanly. */ #if defined(WIN32) || defined(__CYGWIN__) #define PG_BINARY O_BINARY #define PG_BINARY_A "ab" #define PG_BINARY_R "rb" #define PG_BINARY_W "wb" #else #define PG_BINARY 0 #define PG_BINARY_A "a" #define PG_BINARY_R "r" #define PG_BINARY_W "w" #endif /* * Provide prototypes for routines not present in a particular machine's * standard C library. */ #if !HAVE_DECL_FDATASYNC extern int fdatasync(int fildes); #endif /* * Thin wrappers that convert strings to exactly 64-bit integers, matching our * definition of int64. (For the naming, compare that POSIX has * strtoimax()/strtoumax() which return intmax_t/uintmax_t.) */ #ifdef HAVE_LONG_INT_64 #define strtoi64(str, endptr, base) ((int64) strtol(str, endptr, base)) #define strtou64(str, endptr, base) ((uint64) strtoul(str, endptr, base)) #else #define strtoi64(str, endptr, base) ((int64) strtoll(str, endptr, base)) #define strtou64(str, endptr, base) ((uint64) strtoull(str, endptr, base)) #endif /* * Similarly, wrappers around labs()/llabs() matching our int64. */ #ifdef HAVE_LONG_INT_64 #define i64abs(i) labs(i) #else #define i64abs(i) llabs(i) #endif /* * Use "extern PGDLLIMPORT ..." to declare variables that are defined * in the core backend and need to be accessible by loadable modules. * No special marking is required on most ports. */ #ifndef PGDLLIMPORT #define PGDLLIMPORT #endif /* * Use "extern PGDLLEXPORT ..." to declare functions that are defined in * loadable modules and need to be callable by the core backend or other * loadable modules. * If the compiler knows __attribute__((visibility("*"))), we use that, * unless we already have a platform-specific definition. Otherwise, * no special marking is required. */ #ifndef PGDLLEXPORT #ifdef HAVE_VISIBILITY_ATTRIBUTE #define PGDLLEXPORT __attribute__((visibility("default"))) #else #define PGDLLEXPORT #endif #endif /* * The following is used as the arg list for signal handlers. Any ports * that take something other than an int argument should override this in * their pg_config_os.h file. Note that variable names are required * because it is used in both the prototypes as well as the definitions. * Note also the long name. We expect that this won't collide with * other names causing compiler warnings. */ #ifndef SIGNAL_ARGS #define SIGNAL_ARGS int postgres_signal_arg #endif /* * When there is no sigsetjmp, its functionality is provided by plain * setjmp. We now support the case only on Windows. However, it seems * that MinGW-64 has some longstanding issues in its setjmp support, * so on that toolchain we cheat and use gcc's builtins. */ #ifdef WIN32 #ifdef __MINGW64__ typedef intptr_t sigjmp_buf[5]; #define sigsetjmp(x,y) __builtin_setjmp(x) #define siglongjmp __builtin_longjmp #else /* !__MINGW64__ */ #define sigjmp_buf jmp_buf #define sigsetjmp(x,y) setjmp(x) #define siglongjmp longjmp #endif /* __MINGW64__ */ #endif /* WIN32 */ /* /port compatibility functions */ #endif /* C_H */ /*------------------------------------------------------------------------- * * pg_list.h * interface for PostgreSQL generic list package * * Once upon a time, parts of Postgres were written in Lisp and used real * cons-cell lists for major data structures. When that code was rewritten * in C, we initially had a faithful emulation of cons-cell lists, which * unsurprisingly was a performance bottleneck. A couple of major rewrites * later, these data structures are actually simple expansible arrays; * but the "List" name and a lot of the notation survives. * * One important concession to the original implementation is that an empty * list is always represented by a null pointer (preferentially written NIL). * Non-empty lists have a header, which will not be relocated as long as the * list remains non-empty, and an expansible data array. * * We support four types of lists: * * T_List: lists of pointers * (in practice usually pointers to Nodes, but not always; * declared as "void *" to minimize casting annoyances) * T_IntList: lists of integers * T_OidList: lists of Oids * T_XidList: lists of TransactionIds * (the XidList infrastructure is less complete than the other cases) * * (At the moment, ints, Oids, and XIDs are the same size, but they may not * always be so; be careful to use the appropriate list type for your data.) * * * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/nodes/pg_list.h * *------------------------------------------------------------------------- */ #ifndef PG_LIST_H #define PG_LIST_H typedef union ListCell { void *ptr_value; int int_value; Oid oid_value; TransactionId xid_value; } ListCell; typedef struct List { NodeTag type; /* T_List, T_IntList, T_OidList, or T_XidList */ int length; /* number of elements currently present */ int max_length; /* allocated length of elements[] */ ListCell *elements; /* re-allocatable array of cells */ /* We may allocate some cells along with the List header: */ ListCell initial_elements[FLEXIBLE_ARRAY_MEMBER]; /* If elements == initial_elements, it's not a separate allocation */ } List; /* * The *only* valid representation of an empty list is NIL; in other * words, a non-NIL list is guaranteed to have length >= 1. */ #define NIL ((List *) NULL) /* * State structs for various looping macros below. */ typedef struct ForEachState { const List *l; /* list we're looping through */ int i; /* current element index */ } ForEachState; typedef struct ForBothState { const List *l1; /* lists we're looping through */ const List *l2; int i; /* common element index */ } ForBothState; typedef struct ForBothCellState { const List *l1; /* lists we're looping through */ const List *l2; int i1; /* current element indexes */ int i2; } ForBothCellState; typedef struct ForThreeState { const List *l1; /* lists we're looping through */ const List *l2; const List *l3; int i; /* common element index */ } ForThreeState; typedef struct ForFourState { const List *l1; /* lists we're looping through */ const List *l2; const List *l3; const List *l4; int i; /* common element index */ } ForFourState; typedef struct ForFiveState { const List *l1; /* lists we're looping through */ const List *l2; const List *l3; const List *l4; const List *l5; int i; /* common element index */ } ForFiveState; /* * These routines are small enough, and used often enough, to justify being * inline. */ /* Fetch address of list's first cell; NULL if empty list */ static inline ListCell * list_head(const List *l) { return l ? &l->elements[0] : NULL; } /* Fetch address of list's last cell; NULL if empty list */ static inline ListCell * list_tail(const List *l) { return l ? &l->elements[l->length - 1] : NULL; } /* Fetch address of list's second cell, if it has one, else NULL */ static inline ListCell * list_second_cell(const List *l) { if (l && l->length >= 2) return &l->elements[1]; else return NULL; } /* Fetch list's length */ static inline int list_length(const List *l) { return l ? l->length : 0; } /* * Macros to access the data values within List cells. * * Note that with the exception of the "xxx_node" macros, these are * lvalues and can be assigned to. * * NB: There is an unfortunate legacy from a previous incarnation of * the List API: the macro lfirst() was used to mean "the data in this * cons cell". To avoid changing every usage of lfirst(), that meaning * has been kept. As a result, lfirst() takes a ListCell and returns * the data it contains; to get the data in the first cell of a * List, use linitial(). Worse, lsecond() is more closely related to * linitial() than lfirst(): given a List, lsecond() returns the data * in the second list cell. */ #define lfirst(lc) ((lc)->ptr_value) #define lfirst_int(lc) ((lc)->int_value) #define lfirst_oid(lc) ((lc)->oid_value) #define lfirst_xid(lc) ((lc)->xid_value) #define lfirst_node(type,lc) castNode(type, lfirst(lc)) #define linitial(l) lfirst(list_nth_cell(l, 0)) #define linitial_int(l) lfirst_int(list_nth_cell(l, 0)) #define linitial_oid(l) lfirst_oid(list_nth_cell(l, 0)) #define linitial_node(type,l) castNode(type, linitial(l)) #define lsecond(l) lfirst(list_nth_cell(l, 1)) #define lsecond_int(l) lfirst_int(list_nth_cell(l, 1)) #define lsecond_oid(l) lfirst_oid(list_nth_cell(l, 1)) #define lsecond_node(type,l) castNode(type, lsecond(l)) #define lthird(l) lfirst(list_nth_cell(l, 2)) #define lthird_int(l) lfirst_int(list_nth_cell(l, 2)) #define lthird_oid(l) lfirst_oid(list_nth_cell(l, 2)) #define lthird_node(type,l) castNode(type, lthird(l)) #define lfourth(l) lfirst(list_nth_cell(l, 3)) #define lfourth_int(l) lfirst_int(list_nth_cell(l, 3)) #define lfourth_oid(l) lfirst_oid(list_nth_cell(l, 3)) #define lfourth_node(type,l) castNode(type, lfourth(l)) #define llast(l) lfirst(list_last_cell(l)) #define llast_int(l) lfirst_int(list_last_cell(l)) #define llast_oid(l) lfirst_oid(list_last_cell(l)) #define llast_xid(l) lfirst_xid(list_last_cell(l)) #define llast_node(type,l) castNode(type, llast(l)) /* * Convenience macros for building fixed-length lists */ #define list_make_ptr_cell(v) ((ListCell) {.ptr_value = (v)}) #define list_make_int_cell(v) ((ListCell) {.int_value = (v)}) #define list_make_oid_cell(v) ((ListCell) {.oid_value = (v)}) #define list_make_xid_cell(v) ((ListCell) {.xid_value = (v)}) #define list_make1(x1) \ list_make1_impl(T_List, list_make_ptr_cell(x1)) #define list_make2(x1,x2) \ list_make2_impl(T_List, list_make_ptr_cell(x1), list_make_ptr_cell(x2)) #define list_make3(x1,x2,x3) \ list_make3_impl(T_List, list_make_ptr_cell(x1), list_make_ptr_cell(x2), \ list_make_ptr_cell(x3)) #define list_make4(x1,x2,x3,x4) \ list_make4_impl(T_List, list_make_ptr_cell(x1), list_make_ptr_cell(x2), \ list_make_ptr_cell(x3), list_make_ptr_cell(x4)) #define list_make5(x1,x2,x3,x4,x5) \ list_make5_impl(T_List, list_make_ptr_cell(x1), list_make_ptr_cell(x2), \ list_make_ptr_cell(x3), list_make_ptr_cell(x4), \ list_make_ptr_cell(x5)) #define list_make1_int(x1) \ list_make1_impl(T_IntList, list_make_int_cell(x1)) #define list_make2_int(x1,x2) \ list_make2_impl(T_IntList, list_make_int_cell(x1), list_make_int_cell(x2)) #define list_make3_int(x1,x2,x3) \ list_make3_impl(T_IntList, list_make_int_cell(x1), list_make_int_cell(x2), \ list_make_int_cell(x3)) #define list_make4_int(x1,x2,x3,x4) \ list_make4_impl(T_IntList, list_make_int_cell(x1), list_make_int_cell(x2), \ list_make_int_cell(x3), list_make_int_cell(x4)) #define list_make5_int(x1,x2,x3,x4,x5) \ list_make5_impl(T_IntList, list_make_int_cell(x1), list_make_int_cell(x2), \ list_make_int_cell(x3), list_make_int_cell(x4), \ list_make_int_cell(x5)) #define list_make1_oid(x1) \ list_make1_impl(T_OidList, list_make_oid_cell(x1)) #define list_make2_oid(x1,x2) \ list_make2_impl(T_OidList, list_make_oid_cell(x1), list_make_oid_cell(x2)) #define list_make3_oid(x1,x2,x3) \ list_make3_impl(T_OidList, list_make_oid_cell(x1), list_make_oid_cell(x2), \ list_make_oid_cell(x3)) #define list_make4_oid(x1,x2,x3,x4) \ list_make4_impl(T_OidList, list_make_oid_cell(x1), list_make_oid_cell(x2), \ list_make_oid_cell(x3), list_make_oid_cell(x4)) #define list_make5_oid(x1,x2,x3,x4,x5) \ list_make5_impl(T_OidList, list_make_oid_cell(x1), list_make_oid_cell(x2), \ list_make_oid_cell(x3), list_make_oid_cell(x4), \ list_make_oid_cell(x5)) #define list_make1_xid(x1) \ list_make1_impl(T_XidList, list_make_xid_cell(x1)) #define list_make2_xid(x1,x2) \ list_make2_impl(T_XidList, list_make_xid_cell(x1), list_make_xid_cell(x2)) #define list_make3_xid(x1,x2,x3) \ list_make3_impl(T_XidList, list_make_xid_cell(x1), list_make_xid_cell(x2), \ list_make_xid_cell(x3)) #define list_make4_xid(x1,x2,x3,x4) \ list_make4_impl(T_XidList, list_make_xid_cell(x1), list_make_xid_cell(x2), \ list_make_xid_cell(x3), list_make_xid_cell(x4)) #define list_make5_xid(x1,x2,x3,x4,x5) \ list_make5_impl(T_XidList, list_make_xid_cell(x1), list_make_xid_cell(x2), \ list_make_xid_cell(x3), list_make_xid_cell(x4), \ list_make_xid_cell(x5)) /* * Locate the n'th cell (counting from 0) of the list. * It is an assertion failure if there is no such cell. */ static inline ListCell * list_nth_cell(const List *list, int n) { Assert(list != NIL); Assert(n >= 0 && n < list->length); return &list->elements[n]; } /* * Return the last cell in a non-NIL List. */ static inline ListCell * list_last_cell(const List *list) { Assert(list != NIL); return &list->elements[list->length - 1]; } /* * Return the pointer value contained in the n'th element of the * specified list. (List elements begin at 0.) */ static inline void * list_nth(const List *list, int n) { Assert(IsA(list, List)); return lfirst(list_nth_cell(list, n)); } /* * Return the integer value contained in the n'th element of the * specified list. */ static inline int list_nth_int(const List *list, int n) { Assert(IsA(list, IntList)); return lfirst_int(list_nth_cell(list, n)); } /* * Return the OID value contained in the n'th element of the specified * list. */ static inline Oid list_nth_oid(const List *list, int n) { Assert(IsA(list, OidList)); return lfirst_oid(list_nth_cell(list, n)); } #define list_nth_node(type,list,n) castNode(type, list_nth(list, n)) /* * Get the given ListCell's index (from 0) in the given List. */ static inline int list_cell_number(const List *l, const ListCell *c) { Assert(c >= &l->elements[0] && c < &l->elements[l->length]); return c - l->elements; } /* * Get the address of the next cell after "c" within list "l", or NULL if none. */ static inline ListCell * lnext(const List *l, const ListCell *c) { Assert(c >= &l->elements[0] && c < &l->elements[l->length]); c++; if (c < &l->elements[l->length]) return (ListCell *) c; else return NULL; } /* * foreach - * a convenience macro for looping through a list * * "cell" must be the name of a "ListCell *" variable; it's made to point * to each List element in turn. "cell" will be NULL after normal exit from * the loop, but an early "break" will leave it pointing at the current * List element. * * Beware of changing the List object while the loop is iterating. * The current semantics are that we examine successive list indices in * each iteration, so that insertion or deletion of list elements could * cause elements to be re-visited or skipped unexpectedly. Previous * implementations of foreach() behaved differently. However, it's safe * to append elements to the List (or in general, insert them after the * current element); such new elements are guaranteed to be visited. * Also, the current element of the List can be deleted, if you use * foreach_delete_current() to do so. BUT: either of these actions will * invalidate the "cell" pointer for the remainder of the current iteration. */ #define foreach(cell, lst) \ for (ForEachState cell##__state = {(lst), 0}; \ (cell##__state.l != NIL && \ cell##__state.i < cell##__state.l->length) ? \ (cell = &cell##__state.l->elements[cell##__state.i], true) : \ (cell = NULL, false); \ cell##__state.i++) /* * foreach_delete_current - * delete the current list element from the List associated with a * surrounding foreach() loop, returning the new List pointer. * * This is similar to list_delete_cell(), but it also works when using * for_each_xyz macros that don't require passing in a "ListCell *". * Furthermore it adjusts the foreach loop's state so that no list elements * will be missed. Do not delete elements from an active foreach loop's list in * any other way! */ #define foreach_delete_current(lst, var) \ ((List *) (var##__state.l = list_delete_cell(lst, &var##__state.l->elements[var##__state.i--]))) /* * foreach_current_index - * get the zero-based list index of a surrounding foreach() loop's * current element; pass the name of the "ListCell *" iterator variable. * * Beware of using this after foreach_delete_current(); the value will be * out of sync for the rest of the current loop iteration. Anyway, since * you just deleted the current element, the value is pretty meaningless. */ #define foreach_current_index(cell) (cell##__state.i) /* * for_each_from - * Like foreach(), but start from the N'th (zero-based) list element, * not necessarily the first one. * * It's okay for N to exceed the list length, but not for it to be negative. * * The caveats for foreach() apply equally here. */ #define for_each_from(cell, lst, N) \ for (ForEachState cell##__state = for_each_from_setup(lst, N); \ (cell##__state.l != NIL && \ cell##__state.i < cell##__state.l->length) ? \ (cell = &cell##__state.l->elements[cell##__state.i], true) : \ (cell = NULL, false); \ cell##__state.i++) static inline ForEachState for_each_from_setup(const List *lst, int N) { ForEachState r = {lst, N}; Assert(N >= 0); return r; } /* * for_each_cell - * a convenience macro which loops through a list starting from a * specified cell * * The caveats for foreach() apply equally here. */ #define for_each_cell(cell, lst, initcell) \ for (ForEachState cell##__state = for_each_cell_setup(lst, initcell); \ (cell##__state.l != NIL && \ cell##__state.i < cell##__state.l->length) ? \ (cell = &cell##__state.l->elements[cell##__state.i], true) : \ (cell = NULL, false); \ cell##__state.i++) static inline ForEachState for_each_cell_setup(const List *lst, const ListCell *initcell) { ForEachState r = {lst, initcell ? list_cell_number(lst, initcell) : list_length(lst)}; return r; } #define foreach_internal(type, pointer, var, lst, func) \ for (type pointer var = 0, pointer var##__outerloop = (type pointer) 1; \ var##__outerloop; \ var##__outerloop = 0) \ for (ForEachState var##__state = {(lst), 0}; \ (var##__state.l != NIL && \ var##__state.i < var##__state.l->length && \ (var = func(&var##__state.l->elements[var##__state.i]), true)); \ var##__state.i++) /* * Convenience macros that loop through a list of pointers/ints/oids/xids * without needing a "ListCell *", just a declared variable to store of the * respective type to store the current value in. * * Unlike with foreach() it's not possible to detect if an early "break" * occured by checking the value of the loop variable at the end of the loop. * If you need this, it's recommended to use foreach() instead or manually * track if a break occured by using a boolean flag variable called e.g. * "found". * * The caveats for foreach() apply equally here. */ #define foreach_ptr(type, var, lst) foreach_internal(type, *, var, lst, lfirst) #define foreach_int(var, lst) foreach_internal(int, , var, lst, lfirst_int) #define foreach_oid(var, lst) foreach_internal(Oid, , var, lst, lfirst_oid) #define foreach_xid(var, lst) foreach_internal(TransactionId, , var, lst, lfirst_xid) /* * foreach_node - * The same as foreach_ptr, but when assertions are enabled it verifies that * the element is of the specified node type (using its nodeTag()). */ #define foreach_node(type, var, lst) \ for (type * var = 0, *var##__outerloop = (type *) 1; \ var##__outerloop; \ var##__outerloop = 0) \ for (ForEachState var##__state = {(lst), 0}; \ (var##__state.l != NIL && \ var##__state.i < var##__state.l->length && \ (var = lfirst_node(type, &var##__state.l->elements[var##__state.i]), true));\ var##__state.i++) /* * forboth - * a convenience macro for advancing through two linked lists * simultaneously. This macro loops through both lists at the same * time, stopping when either list runs out of elements. Depending * on the requirements of the call site, it may also be wise to * assert that the lengths of the two lists are equal. (But, if they * are not, some callers rely on the ending cell values being separately * NULL or non-NULL as defined here; don't try to optimize that.) * * The caveats for foreach() apply equally here. */ #define forboth(cell1, list1, cell2, list2) \ for (ForBothState cell1##__state = {(list1), (list2), 0}; \ multi_for_advance_cell(cell1, cell1##__state, l1, i), \ multi_for_advance_cell(cell2, cell1##__state, l2, i), \ (cell1 != NULL && cell2 != NULL); \ cell1##__state.i++) #define multi_for_advance_cell(cell, state, l, i) \ (cell = (state.l != NIL && state.i < state.l->length) ? \ &state.l->elements[state.i] : NULL) /* * for_both_cell - * a convenience macro which loops through two lists starting from the * specified cells of each. This macro loops through both lists at the same * time, stopping when either list runs out of elements. Depending on the * requirements of the call site, it may also be wise to assert that the * lengths of the two lists are equal, and initcell1 and initcell2 are at * the same position in the respective lists. * * The caveats for foreach() apply equally here. */ #define for_both_cell(cell1, list1, initcell1, cell2, list2, initcell2) \ for (ForBothCellState cell1##__state = \ for_both_cell_setup(list1, initcell1, list2, initcell2); \ multi_for_advance_cell(cell1, cell1##__state, l1, i1), \ multi_for_advance_cell(cell2, cell1##__state, l2, i2), \ (cell1 != NULL && cell2 != NULL); \ cell1##__state.i1++, cell1##__state.i2++) static inline ForBothCellState for_both_cell_setup(const List *list1, const ListCell *initcell1, const List *list2, const ListCell *initcell2) { ForBothCellState r = {list1, list2, initcell1 ? list_cell_number(list1, initcell1) : list_length(list1), initcell2 ? list_cell_number(list2, initcell2) : list_length(list2)}; return r; } /* * forthree - * the same for three lists */ #define forthree(cell1, list1, cell2, list2, cell3, list3) \ for (ForThreeState cell1##__state = {(list1), (list2), (list3), 0}; \ multi_for_advance_cell(cell1, cell1##__state, l1, i), \ multi_for_advance_cell(cell2, cell1##__state, l2, i), \ multi_for_advance_cell(cell3, cell1##__state, l3, i), \ (cell1 != NULL && cell2 != NULL && cell3 != NULL); \ cell1##__state.i++) /* * forfour - * the same for four lists */ #define forfour(cell1, list1, cell2, list2, cell3, list3, cell4, list4) \ for (ForFourState cell1##__state = {(list1), (list2), (list3), (list4), 0}; \ multi_for_advance_cell(cell1, cell1##__state, l1, i), \ multi_for_advance_cell(cell2, cell1##__state, l2, i), \ multi_for_advance_cell(cell3, cell1##__state, l3, i), \ multi_for_advance_cell(cell4, cell1##__state, l4, i), \ (cell1 != NULL && cell2 != NULL && cell3 != NULL && cell4 != NULL); \ cell1##__state.i++) /* * forfive - * the same for five lists */ #define forfive(cell1, list1, cell2, list2, cell3, list3, cell4, list4, cell5, list5) \ for (ForFiveState cell1##__state = {(list1), (list2), (list3), (list4), (list5), 0}; \ multi_for_advance_cell(cell1, cell1##__state, l1, i), \ multi_for_advance_cell(cell2, cell1##__state, l2, i), \ multi_for_advance_cell(cell3, cell1##__state, l3, i), \ multi_for_advance_cell(cell4, cell1##__state, l4, i), \ multi_for_advance_cell(cell5, cell1##__state, l5, i), \ (cell1 != NULL && cell2 != NULL && cell3 != NULL && \ cell4 != NULL && cell5 != NULL); \ cell1##__state.i++) /* Functions in src/backend/nodes/list.c */ extern List *list_make1_impl(NodeTag t, ListCell datum1); extern List *list_make2_impl(NodeTag t, ListCell datum1, ListCell datum2); extern List *list_make3_impl(NodeTag t, ListCell datum1, ListCell datum2, ListCell datum3); extern List *list_make4_impl(NodeTag t, ListCell datum1, ListCell datum2, ListCell datum3, ListCell datum4); extern List *list_make5_impl(NodeTag t, ListCell datum1, ListCell datum2, ListCell datum3, ListCell datum4, ListCell datum5); extern pg_nodiscard List *lappend(List *list, void *datum); extern pg_nodiscard List *lappend_int(List *list, int datum); extern pg_nodiscard List *lappend_oid(List *list, Oid datum); extern pg_nodiscard List *lappend_xid(List *list, TransactionId datum); extern pg_nodiscard List *list_insert_nth(List *list, int pos, void *datum); extern pg_nodiscard List *list_insert_nth_int(List *list, int pos, int datum); extern pg_nodiscard List *list_insert_nth_oid(List *list, int pos, Oid datum); extern pg_nodiscard List *lcons(void *datum, List *list); extern pg_nodiscard List *lcons_int(int datum, List *list); extern pg_nodiscard List *lcons_oid(Oid datum, List *list); extern pg_nodiscard List *list_concat(List *list1, const List *list2); extern pg_nodiscard List *list_concat_copy(const List *list1, const List *list2); extern pg_nodiscard List *list_truncate(List *list, int new_size); extern bool list_member(const List *list, const void *datum); extern bool list_member_ptr(const List *list, const void *datum); extern bool list_member_int(const List *list, int datum); extern bool list_member_oid(const List *list, Oid datum); extern bool list_member_xid(const List *list, TransactionId datum); extern pg_nodiscard List *list_delete(List *list, void *datum); extern pg_nodiscard List *list_delete_ptr(List *list, void *datum); extern pg_nodiscard List *list_delete_int(List *list, int datum); extern pg_nodiscard List *list_delete_oid(List *list, Oid datum); extern pg_nodiscard List *list_delete_first(List *list); extern pg_nodiscard List *list_delete_last(List *list); extern pg_nodiscard List *list_delete_first_n(List *list, int n); extern pg_nodiscard List *list_delete_nth_cell(List *list, int n); extern pg_nodiscard List *list_delete_cell(List *list, ListCell *cell); extern List *list_union(const List *list1, const List *list2); extern List *list_union_ptr(const List *list1, const List *list2); extern List *list_union_int(const List *list1, const List *list2); extern List *list_union_oid(const List *list1, const List *list2); extern List *list_intersection(const List *list1, const List *list2); extern List *list_intersection_int(const List *list1, const List *list2); /* currently, there's no need for list_intersection_ptr etc */ extern List *list_difference(const List *list1, const List *list2); extern List *list_difference_ptr(const List *list1, const List *list2); extern List *list_difference_int(const List *list1, const List *list2); extern List *list_difference_oid(const List *list1, const List *list2); extern pg_nodiscard List *list_append_unique(List *list, void *datum); extern pg_nodiscard List *list_append_unique_ptr(List *list, void *datum); extern pg_nodiscard List *list_append_unique_int(List *list, int datum); extern pg_nodiscard List *list_append_unique_oid(List *list, Oid datum); extern pg_nodiscard List *list_concat_unique(List *list1, const List *list2); extern pg_nodiscard List *list_concat_unique_ptr(List *list1, const List *list2); extern pg_nodiscard List *list_concat_unique_int(List *list1, const List *list2); extern pg_nodiscard List *list_concat_unique_oid(List *list1, const List *list2); extern void list_deduplicate_oid(List *list); extern void list_free(List *list); extern void list_free_deep(List *list); extern pg_nodiscard List *list_copy(const List *oldlist); extern pg_nodiscard List *list_copy_head(const List *oldlist, int len); extern pg_nodiscard List *list_copy_tail(const List *oldlist, int nskip); extern pg_nodiscard List *list_copy_deep(const List *oldlist); typedef int (*list_sort_comparator) (const ListCell *a, const ListCell *b); extern void list_sort(List *list, list_sort_comparator cmp); extern int list_int_cmp(const ListCell *p1, const ListCell *p2); extern int list_oid_cmp(const ListCell *p1, const ListCell *p2); #endif /* PG_LIST_H */ extern inline uint32_t do_something_macro(List *intlist){ uint32_t sum = 0; foreach_int(myint, intlist) { sum += myint; printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); printf("a"); } return sum; } /* extern inline uint32_t do_something(List *intlist){ uint32_t sum = 0; for (int myint = 0, myint__outerloop = (int) 1; myint__outerloop; myint__outerloop = 0) for (ForEachState myint__state = {(intlist), 0}; (myint__state.l != NIL && myint__state.i < myint__state.l->length && (myint = lfirst_int(&myint__state.l->elements[myint__state.i]), true)); myint__state.i++) { sum += myint; } return sum; } */
Become a Patron
Sponsor on GitHub
Donate via PayPal
Source on GitHub
Mailing list
Installed libraries
Wiki
Report an issue
How it works
Contact the author
CE on Mastodon
About the author
Statistics
Changelog
Version tree