Merge remote-tracking branch 'origin/master' into llvm10

This commit is contained in:
Andrew Kelley
2020-01-16 13:01:36 -05:00
856 changed files with 73631 additions and 35008 deletions
+3
View File
@@ -3,8 +3,11 @@ packages:
- cmake
- py27-s3cmd
- wget
- curl
- jq
secrets:
- 6c60aaee-92e7-4e7d-812c-114817689b4d
- dd0bd962-7664-4d3e-b0f3-41c9ee96b8b8
sources:
- https://github.com/ziglang/zig
tasks:
+17 -4
View File
@@ -10,10 +10,14 @@ if(NOT CMAKE_INSTALL_PREFIX)
"Directory to install zig to" FORCE)
endif()
set(CMAKE_USER_MAKE_RULES_OVERRIDE
${CMAKE_CURRENT_SOURCE_DIR}/cmake/c_flag_overrides.cmake)
set(CMAKE_USER_MAKE_RULES_OVERRIDE_CXX
${CMAKE_CURRENT_SOURCE_DIR}/cmake/cxx_flag_overrides.cmake)
project(zig C CXX)
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH})
set(ZIG_VERSION_MAJOR 0)
set(ZIG_VERSION_MINOR 5)
set(ZIG_VERSION_PATCH 0)
@@ -42,6 +46,7 @@ message("Configuring zig version ${ZIG_VERSION}")
set(ZIG_STATIC off CACHE BOOL "Attempt to build a static zig executable (not compatible with glibc)")
set(ZIG_STATIC_LLVM off CACHE BOOL "Prefer linking against static LLVM libraries")
set(ZIG_SKIP_INSTALL_LIB_FILES off CACHE BOOL "Disable copying lib/ files to install prefix")
set(ZIG_ENABLE_MEM_PROFILE off CACHE BOOL "Activate memory usage instrumentation")
if(ZIG_STATIC)
set(ZIG_STATIC_LLVM "on")
@@ -433,16 +438,20 @@ set(ZIG_MAIN_SRC "${CMAKE_SOURCE_DIR}/src/main.cpp")
# This is our shim which will be replaced by libuserland written in Zig.
set(ZIG0_SHIM_SRC "${CMAKE_SOURCE_DIR}/src/userland.cpp")
if(ZIG_ENABLE_MEM_PROFILE)
set(ZIG_SOURCES_MEM_PROFILE "${CMAKE_SOURCE_DIR}/src/memory_profiling.cpp")
endif()
set(ZIG_SOURCES
"${CMAKE_SOURCE_DIR}/src/analyze.cpp"
"${CMAKE_SOURCE_DIR}/src/ast_render.cpp"
"${CMAKE_SOURCE_DIR}/src/bigfloat.cpp"
"${CMAKE_SOURCE_DIR}/src/bigint.cpp"
"${CMAKE_SOURCE_DIR}/src/buffer.cpp"
"${CMAKE_SOURCE_DIR}/src/c_tokenizer.cpp"
"${CMAKE_SOURCE_DIR}/src/cache_hash.cpp"
"${CMAKE_SOURCE_DIR}/src/codegen.cpp"
"${CMAKE_SOURCE_DIR}/src/compiler.cpp"
"${CMAKE_SOURCE_DIR}/src/dump_analysis.cpp"
"${CMAKE_SOURCE_DIR}/src/errmsg.cpp"
"${CMAKE_SOURCE_DIR}/src/error.cpp"
"${CMAKE_SOURCE_DIR}/src/glibc.cpp"
@@ -453,11 +462,10 @@ set(ZIG_SOURCES
"${CMAKE_SOURCE_DIR}/src/os.cpp"
"${CMAKE_SOURCE_DIR}/src/parser.cpp"
"${CMAKE_SOURCE_DIR}/src/range_set.cpp"
"${CMAKE_SOURCE_DIR}/src/stack_report.cpp"
"${CMAKE_SOURCE_DIR}/src/target.cpp"
"${CMAKE_SOURCE_DIR}/src/tokenizer.cpp"
"${CMAKE_SOURCE_DIR}/src/translate_c.cpp"
"${CMAKE_SOURCE_DIR}/src/util.cpp"
"${ZIG_SOURCES_MEM_PROFILE}"
)
set(OPTIMIZED_C_SOURCES
"${CMAKE_SOURCE_DIR}/src/blake2b.c"
@@ -624,5 +632,10 @@ set_target_properties(zig PROPERTIES
LINK_FLAGS ${EXE_LDFLAGS}
)
target_link_libraries(zig compiler "${LIBUSERLAND}")
if(MSVC)
target_link_libraries(zig ntdll.lib)
elseif(MINGW)
target_link_libraries(zig ntdll)
endif()
add_dependencies(zig zig_build_libuserland)
install(TARGETS zig DESTINATION bin)
+58
View File
@@ -123,3 +123,61 @@ When developing on Linux, another option is available to you: `-Denable-wine`.
This will enable running behavior tests and std lib tests with Wine. It's
recommended for Linux users to install Wine and enable this testing option
when editing the standard library or anything Windows-related.
#### Improving Translate-C
Please read the [Editing Source Code](#editing-source-code) section as a
prerequisite to this one.
`translate-c` is a feature provided by Zig that converts C source code into
Zig source code. It powers the `zig translate-c` command as well as
[@cImport](https://ziglang.org/documentation/master/#cImport), allowing Zig
code to not only take advantage of function prototypes defined in .h files,
but also `static inline` functions written in C, and even some macros.
This feature works by using libclang API to parse and semantically analyze
C/C++ files, and then based on the provided AST and type information,
generating Zig AST, and finally using the mechanisms of `zig fmt` to render
the Zig AST to a file.
The relevant tests for this feature are:
* `test/run_translated_c.zig` - each test case is C code with a `main` function. The C code
is translated into Zig code, compiled, and run, and tests that the expected output is the
same, and that the program exits cleanly. This kind of test coverage is preferred, when
possible, because it makes sure that the resulting Zig code is actually viable.
* `test/translate_c.zig` - each test case is C code, with a list of expected strings which
must be found in the resulting Zig code. This kind of test is more precise in what it
measures, but does not provide test coverage of whether the resulting Zig code is valid.
This feature is self-hosted, even though Zig is not fully self-hosted yet. In the Zig source
repo, we maintain a C API on top of Clang's C++ API:
* `src/zig_clang.h` - the C API that we maintain on top of Clang's C++ API. This
file does not include any Clang's C++ headers. Instead, C types and C enums are defined
here.
* `src/zig_clang.cpp` - a lightweight wrapper that fulfills the C API on top of the
C++ API. It takes advantage of `static_assert` to make sure we get compile errors when
Clang's C++ API changes. This one file necessarily does include Clang's C++ headers, which
makes it the slowest-to-compile source file in all of Zig's codebase.
* `src-self-hosted/clang.zig` - the Zig equivalent of `src/zig_clang.h`. This is a manually
maintained list of types and functions that are ABI-compatible with the Clang C API we
maintain. In theory this could be generated by running translate-c on `src/zig_clang.h`,
but that would introduce a dependency cycle, since we are using this file to implement
translate-c.
Finally, the actual source code for the translate-c feature is
`src-self-hosted/translate_c.zig`. This code uses the Clang C API exposed by
`src-self-hosted/clang.zig`, and produces Zig AST.
The steps for contributing to translate-c look like this:
1. Identify a test case you want to improve. Add it as a run-translated-c test
case (usually preferable), or as a translate-c test case.
2. Edit `src-self-hosted/translate_c.zig` to improve the behavior.
3. Run the relevant tests: `./zig build test-run-translated-c test-translate-c`
+2 -2
View File
@@ -1,7 +1,7 @@
![ZIG](https://ziglang.org/zig-logo.svg)
A general-purpose programming language designed for **robustness**,
**optimality**, and **maintainability**.
A general-purpose programming language and toolchain for maintaining
**robust**, **optimal**, and **reusable** software.
## Resources
+31 -29
View File
@@ -20,10 +20,10 @@ pub fn build(b: *Builder) !void {
const rel_zig_exe = try fs.path.relative(b.allocator, b.build_root, b.zig_exe);
const langref_out_path = fs.path.join(
b.allocator,
[_][]const u8{ b.cache_root, "langref.html" },
&[_][]const u8{ b.cache_root, "langref.html" },
) catch unreachable;
var docgen_cmd = docgen_exe.run();
docgen_cmd.addArgs([_][]const u8{
docgen_cmd.addArgs(&[_][]const u8{
rel_zig_exe,
"doc" ++ fs.path.sep_str ++ "langref.html.in",
langref_out_path,
@@ -36,7 +36,7 @@ pub fn build(b: *Builder) !void {
const test_step = b.step("test", "Run all the tests");
// find the stage0 build artifacts because we're going to re-use config.h and zig_cpp library
const build_info = try b.exec([_][]const u8{
const build_info = try b.exec(&[_][]const u8{
b.zig_exe,
"BUILD_INFO",
});
@@ -54,8 +54,9 @@ pub fn build(b: *Builder) !void {
var test_stage2 = b.addTest("src-self-hosted/test.zig");
test_stage2.setBuildMode(builtin.Mode.Debug);
test_stage2.addPackagePath("stage2_tests", "test/stage2/test.zig");
const fmt_build_zig = b.addFmt([_][]const u8{"build.zig"});
const fmt_build_zig = b.addFmt(&[_][]const u8{"build.zig"});
var exe = b.addExecutable("zig", "src-self-hosted/main.zig");
exe.setBuildMode(mode);
@@ -72,9 +73,9 @@ pub fn build(b: *Builder) !void {
const skip_non_native = b.option(bool, "skip-non-native", "Main test suite skips non-native builds") orelse false;
const skip_libc = b.option(bool, "skip-libc", "Main test suite skips tests that link libc") orelse false;
const skip_self_hosted = b.option(bool, "skip-self-hosted", "Main test suite skips building self hosted compiler") orelse false;
if (!skip_self_hosted) {
// TODO re-enable this after https://github.com/ziglang/zig/issues/2377
//test_step.dependOn(&exe.step);
if (!skip_self_hosted and builtin.os == .linux) {
// TODO evented I/O other OS's
test_step.dependOn(&exe.step);
}
const only_install_lib_files = b.option(bool, "lib-files-only", "Only install library files") orelse false;
@@ -87,7 +88,7 @@ pub fn build(b: *Builder) !void {
.source_dir = "lib",
.install_dir = .Lib,
.install_subdir = "zig",
.exclude_extensions = [_][]const u8{ "test.zig", "README.md" },
.exclude_extensions = &[_][]const u8{ "test.zig", "README.md" },
});
const test_filter = b.option([]const u8, "test-filter", "Skip tests that do not match filter");
@@ -98,11 +99,7 @@ pub fn build(b: *Builder) !void {
const test_stage2_step = b.step("test-stage2", "Run the stage2 compiler tests");
test_stage2_step.dependOn(&test_stage2.step);
// TODO see https://github.com/ziglang/zig/issues/1364
if (false) {
test_step.dependOn(test_stage2_step);
}
test_step.dependOn(test_stage2_step);
var chosen_modes: [4]builtin.Mode = undefined;
var chosen_mode_index: usize = 0;
@@ -140,6 +137,7 @@ pub fn build(b: *Builder) !void {
test_step.dependOn(tests.addAssembleAndLinkTests(b, test_filter, modes));
test_step.dependOn(tests.addRuntimeSafetyTests(b, test_filter, modes));
test_step.dependOn(tests.addTranslateCTests(b, test_filter));
test_step.dependOn(tests.addRunTranslatedCTests(b, test_filter));
test_step.dependOn(tests.addGenHTests(b, test_filter));
test_step.dependOn(tests.addCompileErrorTests(b, test_filter, modes));
test_step.dependOn(docs_step);
@@ -151,16 +149,16 @@ fn dependOnLib(b: *Builder, lib_exe_obj: var, dep: LibraryDep) void {
}
const lib_dir = fs.path.join(
b.allocator,
[_][]const u8{ dep.prefix, "lib" },
&[_][]const u8{ dep.prefix, "lib" },
) catch unreachable;
for (dep.system_libs.toSliceConst()) |lib| {
const static_bare_name = if (mem.eql(u8, lib, "curses"))
([]const u8)("libncurses.a")
@as([]const u8, "libncurses.a")
else
b.fmt("lib{}.a", lib);
b.fmt("lib{}.a", .{lib});
const static_lib_name = fs.path.join(
b.allocator,
[_][]const u8{ lib_dir, static_bare_name },
&[_][]const u8{ lib_dir, static_bare_name },
) catch unreachable;
const have_static = fileExists(static_lib_name) catch unreachable;
if (have_static) {
@@ -186,10 +184,10 @@ fn fileExists(filename: []const u8) !bool {
}
fn addCppLib(b: *Builder, lib_exe_obj: var, cmake_binary_dir: []const u8, lib_name: []const u8) void {
lib_exe_obj.addObjectFile(fs.path.join(b.allocator, [_][]const u8{
lib_exe_obj.addObjectFile(fs.path.join(b.allocator, &[_][]const u8{
cmake_binary_dir,
"zig_cpp",
b.fmt("{}{}{}", lib_exe_obj.target.libPrefix(), lib_name, lib_exe_obj.target.staticLibSuffix()),
b.fmt("{}{}{}", .{ lib_exe_obj.target.libPrefix(), lib_name, lib_exe_obj.target.staticLibSuffix() }),
}) catch unreachable);
}
@@ -202,22 +200,22 @@ const LibraryDep = struct {
};
fn findLLVM(b: *Builder, llvm_config_exe: []const u8) !LibraryDep {
const shared_mode = try b.exec([_][]const u8{ llvm_config_exe, "--shared-mode" });
const shared_mode = try b.exec(&[_][]const u8{ llvm_config_exe, "--shared-mode" });
const is_static = mem.startsWith(u8, shared_mode, "static");
const libs_output = if (is_static)
try b.exec([_][]const u8{
try b.exec(&[_][]const u8{
llvm_config_exe,
"--libfiles",
"--system-libs",
})
else
try b.exec([_][]const u8{
try b.exec(&[_][]const u8{
llvm_config_exe,
"--libs",
});
const includes_output = try b.exec([_][]const u8{ llvm_config_exe, "--includedir" });
const libdir_output = try b.exec([_][]const u8{ llvm_config_exe, "--libdir" });
const prefix_output = try b.exec([_][]const u8{ llvm_config_exe, "--prefix" });
const includes_output = try b.exec(&[_][]const u8{ llvm_config_exe, "--includedir" });
const libdir_output = try b.exec(&[_][]const u8{ llvm_config_exe, "--libdir" });
const prefix_output = try b.exec(&[_][]const u8{ llvm_config_exe, "--prefix" });
var result = LibraryDep{
.prefix = mem.tokenize(prefix_output, " \r\n").next().?,
@@ -235,6 +233,9 @@ fn findLLVM(b: *Builder, llvm_config_exe: []const u8) !LibraryDep {
if (fs.path.isAbsolute(lib_arg)) {
try result.libs.append(lib_arg);
} else {
if (mem.endsWith(u8, lib_arg, ".lib")) {
lib_arg = lib_arg[0 .. lib_arg.len - 4];
}
try result.system_libs.append(lib_arg);
}
}
@@ -341,16 +342,16 @@ fn addCxxKnownPath(
objname: []const u8,
errtxt: ?[]const u8,
) !void {
const path_padded = try b.exec([_][]const u8{
const path_padded = try b.exec(&[_][]const u8{
ctx.cxx_compiler,
b.fmt("-print-file-name={}", objname),
b.fmt("-print-file-name={}", .{objname}),
});
const path_unpadded = mem.tokenize(path_padded, "\r\n").next().?;
if (mem.eql(u8, path_unpadded, objname)) {
if (errtxt) |msg| {
warn("{}", msg);
warn("{}", .{msg});
} else {
warn("Unable to determine path to {}\n", objname);
warn("Unable to determine path to {}\n", .{objname});
}
return error.RequiredLibraryNotFound;
}
@@ -373,6 +374,7 @@ fn addLibUserlandStep(b: *Builder, mode: builtin.Mode) void {
artifact.bundle_compiler_rt = true;
artifact.setTarget(builtin.arch, builtin.os, builtin.abi);
artifact.setBuildMode(mode);
artifact.force_pic = true;
if (mode != .Debug) {
artifact.strip = true;
}
+9 -3
View File
@@ -5,7 +5,7 @@ set -e
BUILDDIR="$(pwd)"
sudo sh -c 'echo "deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-9 main" >> /etc/apt/sources.list'
sudo sh -c 'echo "deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-9 main" >> /etc/apt/sources.list'
wget -O - http://apt.llvm.org/llvm-snapshot.gpg.key|sudo apt-key add -
sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
sudo apt-get update -q
@@ -14,6 +14,10 @@ sudo apt-get remove -y llvm-*
sudo rm -rf /usr/local/*
sudo apt-get install -y libxml2-dev libclang-9-dev llvm-9 llvm-9-dev cmake s3cmd gcc-7 g++-7 qemu
# Make the `zig version` number consistent.
# This will affect the cmake command below.
git config core.abbrev 9
export CC=gcc-7
export CXX=g++-7
mkdir build
@@ -21,11 +25,12 @@ cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
make -j2 install
./zig build test -Denable-qemu
VERSION="$(./zig version)"
if [ "${BUILD_REASON}" != "PullRequest" ]; then
ARTIFACTSDIR="$BUILDDIR/artifacts"
mkdir "$ARTIFACTSDIR"
docker run -i --mount type=bind,source="$ARTIFACTSDIR",target=/z ziglang/static-base:llvm9-1 -j2 $BUILD_SOURCEVERSION
docker run -i --mount type=bind,source="$ARTIFACTSDIR",target=/z ziglang/static-base:llvm9-x86_64 -j2 $BUILD_SOURCEVERSION
TARBALL="$(ls $ARTIFACTSDIR)"
mv "$DOWNLOADSECUREFILE_SECUREFILEPATH" "$HOME/.s3cfg"
s3cmd put -P --add-header="cache-control: public, max-age=31536000, immutable" "$ARTIFACTSDIR/$TARBALL" s3://ziglang.org/builds/
@@ -40,7 +45,7 @@ if [ "${BUILD_REASON}" != "PullRequest" ]; then
echo "\"size\": \"$BYTESIZE\"}" >>$JSONFILE
s3cmd put -P --add-header="Cache-Control: max-age=0, must-revalidate" "$JSONFILE" "s3://ziglang.org/builds/$JSONFILE"
s3cmd put -P "$JSONFILE" "s3://ziglang.org/builds/linux-$VERSION.json"
s3cmd put -P "$JSONFILE" "s3://ziglang.org/builds/x86_64-linux-$VERSION.json"
# `set -x` causes these variables to be mangled.
# See https://developercommunity.visualstudio.com/content/problem/375679/pipeline-variable-incorrectly-inserts-single-quote.html
@@ -48,4 +53,5 @@ if [ "${BUILD_REASON}" != "PullRequest" ]; then
echo "##vso[task.setvariable variable=tarball;isOutput=true]$TARBALL"
echo "##vso[task.setvariable variable=shasum;isOutput=true]$SHASUM"
echo "##vso[task.setvariable variable=bytesize;isOutput=true]$BYTESIZE"
echo "##vso[task.setvariable variable=version;isOutput=true]$VERSION"
fi
+25 -9
View File
@@ -8,7 +8,9 @@ system_profiler SPHardwareDataType
brew install s3cmd gcc@8
ZIGDIR="$(pwd)"
CACHE_BASENAME="llvm+clang-10.0.0-macos-x86_64-gcc8-release"
LLVMVER="10.0.0"
ARCH="x86_64"
CACHE_BASENAME="llvm+clang+lld-$LLVMVER-$ARCH-macos-gcc8-release"
PREFIX="$HOME/$CACHE_BASENAME"
TMPDIR="$HOME/tmpz"
JOBS="-j2"
@@ -44,18 +46,27 @@ else
rm $PREFIX/lib/libz*dylib
cd $TMPDIR
wget https://releases.llvm.org/10.0.0/llvm-10.0.0.src.tar.xz
tar xf llvm-10.0.0.src.tar.xz
cd llvm-10.0.0.src/
wget https://releases.llvm.org/$LLVMVER/llvm-$LLVMVER.src.tar.xz
tar xf llvm-$LLVMVER.src.tar.xz
cd llvm-$LLVMVER.src/
mkdir build
cd build
cmake .. -DCMAKE_INSTALL_PREFIX=$PREFIX -DCMAKE_PREFIX_PATH=$PREFIX -DCMAKE_BUILD_TYPE=Release -DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD="AVR" -DLLVM_ENABLE_LIBXML2=OFF -DLLVM_ENABLE_TERMINFO=OFF
make $JOBS install
cd $TMPDIR
wget https://releases.llvm.org/10.0.0/cfe-10.0.0.src.tar.xz
tar xf cfe-10.0.0.src.tar.xz
cd cfe-10.0.0.src/
wget https://releases.llvm.org/$LLVMVER/cfe-$LLVMVER.src.tar.xz
tar xf cfe-$LLVMVER.src.tar.xz
cd cfe-$LLVMVER.src/
mkdir build
cd build
cmake .. -DCMAKE_INSTALL_PREFIX=$PREFIX -DCMAKE_PREFIX_PATH=$PREFIX -DCMAKE_BUILD_TYPE=Release
make $JOBS install
cd $TMPDIR
wget https://github.com/llvm/llvm-project/releases/download/llvmorg-$LLVMVER/lld-$LLVMVER.src.tar.xz
tar xf lld-$LLVMVER.src.tar.xz
cd lld-$LLVMVER.src/
mkdir build
cd build
cmake .. -DCMAKE_INSTALL_PREFIX=$PREFIX -DCMAKE_PREFIX_PATH=$PREFIX -DCMAKE_BUILD_TYPE=Release
@@ -68,6 +79,11 @@ else
fi
cd $ZIGDIR
# Make the `zig version` number consistent.
# This will affect the cmake command below.
git config core.abbrev 9
mkdir build
cd build
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH=$PREFIX -DCMAKE_INSTALL_PREFIX=$(pwd)/release -DZIG_STATIC=ON
@@ -81,7 +97,7 @@ if [ "${BUILD_REASON}" != "PullRequest" ]; then
rmdir release/bin
VERSION=$(release/zig version)
DIRNAME="zig-macos-x86_64-$VERSION"
DIRNAME="zig-macos-$ARCH-$VERSION"
TARBALL="$DIRNAME.tar.xz"
mv release "$DIRNAME"
tar cfJ "$TARBALL" "$DIRNAME"
@@ -99,7 +115,7 @@ if [ "${BUILD_REASON}" != "PullRequest" ]; then
echo "\"size\": \"$BYTESIZE\"}" >>$JSONFILE
s3cmd put -P --add-header="Cache-Control: max-age=0, must-revalidate" "$JSONFILE" "s3://ziglang.org/builds/$JSONFILE"
s3cmd put -P "$JSONFILE" "s3://ziglang.org/builds/macos-$VERSION.json"
s3cmd put -P "$JSONFILE" "s3://ziglang.org/builds/$ARCH-macos-$VERSION.json"
# `set -x` causes these variables to be mangled.
# See https://developercommunity.visualstudio.com/content/problem/375679/pipeline-variable-incorrectly-inserts-single-quote.html
+12
View File
@@ -0,0 +1,12 @@
#!/bin/sh
# We do not set -x because this would leak the oauth access token.
set +x
set -e
sudo apt-get update -y
sudo apt-get install -y curl jq
OAUTH_TOKEN="$(cat "$DOWNLOADSECUREFILE_SECUREFILEPATH")"
./ci/srht/on_master_success "$VERSION" "$OAUTH_TOKEN"
+7 -15
View File
@@ -14,7 +14,7 @@ jobs:
displayName: 'Build and test'
- job: BuildLinux
pool:
vmImage: 'ubuntu-16.04'
vmImage: 'ubuntu-18.04'
timeoutInMinutes: 360
@@ -44,7 +44,7 @@ jobs:
- script: ci/azure/windows_script.bat
name: main
displayName: 'Build and test'
- job: UpdateDownloadPage
- job: OnMasterSuccess
dependsOn:
- BuildMacOS
- BuildLinux
@@ -53,20 +53,12 @@ jobs:
strategy:
maxParallel: 1
pool:
vmImage: 'ubuntu-16.04'
vmImage: 'ubuntu-18.04'
variables:
macos_tarball: $[ dependencies.BuildMacOS.outputs['main.tarball'] ]
macos_shasum: $[ dependencies.BuildMacOS.outputs['main.shasum'] ]
macos_bytesize: $[ dependencies.BuildMacOS.outputs['main.bytesize'] ]
linux_tarball: $[ dependencies.BuildLinux.outputs['main.tarball'] ]
linux_shasum: $[ dependencies.BuildLinux.outputs['main.shasum'] ]
linux_bytesize: $[ dependencies.BuildLinux.outputs['main.bytesize'] ]
windows_tarball: $[ dependencies.BuildWindows.outputs['main.tarball'] ]
windows_shasum: $[ dependencies.BuildWindows.outputs['main.shasum'] ]
windows_bytesize: $[ dependencies.BuildWindows.outputs['main.bytesize'] ]
version: $[ dependencies.BuildLinux.outputs['main.version'] ]
steps:
- task: DownloadSecureFile@1
inputs:
secureFile: s3cfg
- script: ci/azure/update_download_page
displayName: 'Update download page'
secureFile: oauth_token
- script: ci/azure/on_master_success
displayName: 'master branch success hook'
-41
View File
@@ -1,41 +0,0 @@
#!/bin/sh
set -x
set -e
SRCDIR=$(pwd)
rm -rf .git
sudo apt-get update -y
sudo apt-get install -y s3cmd curl jq
cd "$HOME"
wget "https://ziglang.org/builds/$LINUX_TARBALL"
tar xf $LINUX_TARBALL
ZIGDIR=$(basename -s .tar.xz $LINUX_TARBALL)
ZIG="$ZIGDIR/zig"
LANGREF="$ZIGDIR/langref.html"
VERSION=$($ZIG version)
SRCTARBALLDIR="zig-$VERSION"
export SRC_TARBALL="$SRCTARBALLDIR.tar.xz"
mv "$SRCDIR" "$SRCTARBALLDIR"
tar cfJ "$SRC_TARBALL" "$SRCTARBALLDIR"
export SRC_SHASUM=$(sha256sum $SRC_TARBALL | cut '-d ' -f1)
export SRC_BYTESIZE=$(wc -c < $SRC_TARBALL)
# the freebsd build has to be there too
FREEBSD_JSON=$(curl --fail "https://ziglang.org/builds/freebsd-$VERSION.json" || exit 1)
export FREEBSD_TARBALL="$(echo "$FREEBSD_JSON" | jq .tarball -r)"
export FREEBSD_BYTESIZE="$(echo "$FREEBSD_JSON" | jq .size -r)"
export FREEBSD_SHASUM="$(echo "$FREEBSD_JSON" | jq .shasum -r)"
git clone https://github.com/ziglang/www.ziglang.org --depth 1
cd www.ziglang.org
export MASTER_DATE=$(date +%Y-%m-%d)
env
"../$ZIG" run update-download-page.zig
mv "$DOWNLOADSECUREFILE_SECUREFILEPATH" "$HOME/.s3cfg"
s3cmd put -P --add-header="cache-control: public, max-age=31536000, immutable" "../$SRC_TARBALL" s3://ziglang.org/builds/
s3cmd put -P "../$LANGREF" s3://ziglang.org/documentation/master/index.html --add-header="Cache-Control: max-age=0, must-revalidate"
s3cmd put -P www/download/index.html s3://ziglang.org/download/index.html --add-header="Cache-Control: max-age=0, must-revalidate"
s3cmd put -P www/download/index.json s3://ziglang.org/download/index.json --add-header="Cache-Control: max-age=0, must-revalidate"
+1 -1
View File
@@ -6,5 +6,5 @@ set -e
pacman -Su --needed --noconfirm
pacman -S --needed --noconfirm wget p7zip python3-pip
pip install s3cmd
wget -nv "https://ziglang.org/deps/llvm%2bclang-10.0.0-win64-msvc-release.tar.xz"
wget -nv "https://ziglang.org/deps/llvm%2bclang%2blld-10.0.0-x86_64-windows-msvc-mt.tar.xz"
tar xf llvm+clang-10.0.0-win64-msvc-release.tar.xz
+7 -4
View File
@@ -11,15 +11,18 @@ SET "MSYSTEM=%PREVMSYSTEM%"
SET "ZIGBUILDDIR=%SRCROOT%\build"
SET "ZIGINSTALLDIR=%ZIGBUILDDIR%\dist"
SET "ZIGPREFIXPATH=%SRCROOT%\llvm+clang-10.0.0-win64-msvc-release"
SET "ZIGPREFIXPATH=%SRCROOT%\llvm+clang+lld-10.0.0-x86_64-windows-msvc-mt"
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
REM Make the `zig version` number consistent.
REM This will affect the cmake command below.
git.exe config core.abbrev 9
mkdir %ZIGBUILDDIR%
cd %ZIGBUILDDIR%
REM Here we use MinSizeRel instead of Release to work around https://github.com/ziglang/zig/issues/3024
cmake.exe .. -Thost=x64 -G"Visual Studio 16 2019" -A x64 "-DCMAKE_INSTALL_PREFIX=%ZIGINSTALLDIR%" "-DCMAKE_PREFIX_PATH=%ZIGPREFIXPATH%" -DCMAKE_BUILD_TYPE=MinSizeRel || exit /b
msbuild /p:Configuration=MinSizeRel INSTALL.vcxproj || exit /b
cmake.exe .. -Thost=x64 -G"Visual Studio 16 2019" -A x64 "-DCMAKE_INSTALL_PREFIX=%ZIGINSTALLDIR%" "-DCMAKE_PREFIX_PATH=%ZIGPREFIXPATH%" -DCMAKE_BUILD_TYPE=Release || exit /b
msbuild /maxcpucount /p:Configuration=Release INSTALL.vcxproj || exit /b
"%ZIGINSTALLDIR%\bin\zig.exe" build test || exit /b
+1 -1
View File
@@ -30,7 +30,7 @@ if [ "${BUILD_REASON}" != "PullRequest" ]; then
echo "\"size\": \"$BYTESIZE\"}" >>$JSONFILE
s3cmd put -P --add-header="Cache-Control: max-age=0, must-revalidate" "$JSONFILE" "s3://ziglang.org/builds/$JSONFILE"
s3cmd put -P "$JSONFILE" "s3://ziglang.org/builds/windows-$VERSION.json"
s3cmd put -P "$JSONFILE" "s3://ziglang.org/builds/x86_64-windows-$VERSION.json"
# `set -x` causes these variables to be mangled.
# See https://developercommunity.visualstudio.com/content/problem/375679/pipeline-variable-incorrectly-inserts-single-quote.html
+19
View File
@@ -0,0 +1,19 @@
---
kind: pipeline
name: test-aarch64-linux-musl
platform:
arch: arm64
steps:
- name: build-and-test
image: ziglang/static-base:llvm9-1
environment:
SRHT_OAUTH_TOKEN:
from_secret: SRHT_OAUTH_TOKEN
AWS_ACCESS_KEY_ID:
from_secret: AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY:
from_secret: AWS_SECRET_ACCESS_KEY
commands:
- ./ci/drone/linux_script
+70
View File
@@ -0,0 +1,70 @@
#!/bin/sh
set -x
set -e
TRIPLEARCH="$(uname -m)"
BUILDDIR="$(pwd)"
DISTDIR="$(pwd)/dist"
apk update
apk add py3-pip xz perl-utils jq curl
pip3 install s3cmd
# Make the `zig version` number consistent.
# This will affect the cmake command below.
git config core.abbrev 9
mkdir build
cd build
cmake .. -DCMAKE_BUILD_TYPE=Release "-DCMAKE_INSTALL_PREFIX=$DISTDIR" -DZIG_STATIC=ON -DCMAKE_PREFIX_PATH=/deps/local
make -j$(nproc) install
./zig build test-fmt test-behavior test-std test-compiler-rt -Dskip-release -Dskip-non-native
# TODO test-compare-output is hitting https://github.com/ziglang/zig/issues/3526
./zig build test-standalone test-stack-traces
# TODO test-cli is hitting https://github.com/ziglang/zig/issues/3526
./zig build test-asm-link test-runtime-safety
# TODO test-translate-c is hitting https://github.com/ziglang/zig/issues/3526
./zig build test-gen-h
# TODO test-compile-errors is hitting https://github.com/ziglang/zig/issues/3526
# TODO building docs is hitting https://github.com/ziglang/zig/issues/3526
# TODO full test suite:
#./zig build test
if [ -z "$DRONE_PULL_REQUEST" ]; then
mv ../LICENSE "$DISTDIR/"
# TODO uncomment when the docs are generated
# mv ../zig-cache/langref.html "$DISTDIR/"
mv "$DISTDIR/bin/zig" "$DISTDIR/"
rmdir "$DISTDIR/bin"
GITBRANCH="$DRONE_BRANCH"
VERSION="$("$DISTDIR/zig" version)"
DIRNAME="zig-linux-$TRIPLEARCH-$VERSION"
TARBALL="$DIRNAME.tar.xz"
mv "$DISTDIR" "$DIRNAME"
tar cfJ "$TARBALL" "$DIRNAME"
s3cmd put -P --add-header="cache-control: public, max-age=31536000, immutable" "$TARBALL" s3://ziglang.org/builds/
SHASUM=$(shasum -a 256 $TARBALL | cut '-d ' -f1)
BYTESIZE=$(wc -c < $TARBALL)
JSONFILE="$TRIPLEARCH-linux-$GITBRANCH.json"
touch $JSONFILE
echo "{\"tarball\": \"$TARBALL\"," >>$JSONFILE
echo "\"shasum\": \"$SHASUM\"," >>$JSONFILE
echo "\"size\": \"$BYTESIZE\"}" >>$JSONFILE
s3cmd put -P --add-header="Cache-Control: max-age=0, must-revalidate" "$JSONFILE" "s3://ziglang.org/builds/$JSONFILE"
s3cmd put -P "$JSONFILE" "s3://ziglang.org/builds/$TRIPLEARCH-linux-$VERSION.json"
if [ "$GITBRANCH" = "master" ]; then
# avoid leaking oauth token
set +x
cd "$BUILDDIR"
./ci/srht/on_master_success "$VERSION" "$SRHT_OAUTH_TOKEN"
fi
fi
+16 -2
View File
@@ -13,9 +13,14 @@ wget -nv "https://ziglang.org/builds/$CACHE_BASENAME.tar.xz"
tar xf "$CACHE_BASENAME.tar.xz"
cd $ZIGDIR
# Make the `zig version` number consistent.
# This will affect the cmake command below.
git config core.abbrev 9
mkdir build
cd build
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH=$PREFIX -DCMAKE_INSTALL_PREFIX=$(pwd)/release -DZIG_STATIC=ON
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH=$PREFIX "-DCMAKE_INSTALL_PREFIX=$(pwd)/release" -DZIG_STATIC=ON
make $JOBS install
release/bin/zig build test-fmt
@@ -80,5 +85,14 @@ if [ -f ~/.s3cfg ]; then
echo "\"size\": \"$BYTESIZE\"}" >>$JSONFILE
s3cmd put -P --add-header="Cache-Control: max-age=0, must-revalidate" "$JSONFILE" "s3://ziglang.org/builds/$JSONFILE"
s3cmd put -P "$JSONFILE" "s3://ziglang.org/builds/freebsd-$VERSION.json"
s3cmd put -P "$JSONFILE" "s3://ziglang.org/builds/x86_64-freebsd-$VERSION.json"
if [ "$GITBRANCH" = "master" ]; then
# avoid leaking oauth token
set +x
OAUTH_TOKEN="$(cat ~/.oauth_token)"
cd "$ZIGDIR"
./ci/srht/on_master_success "$VERSION" "$OAUTH_TOKEN"
fi
fi
+39
View File
@@ -0,0 +1,39 @@
#!/bin/sh
# This script must run on a lot of different platforms.
# It assumes that the following things are installed:
# * curl
# * jq
# * cat
# We do not set -x because this would leak the oauth access token.
set +x
set -e
VERSION="$1"
OAUTH_TOKEN="$2"
YML_FILE="tmp.yml"
cat <<EOF >"$YML_FILE"
image: alpine/latest
packages:
- py3-pip
- curl
- jq
- xz
secrets:
- 6c60aaee-92e7-4e7d-812c-114817689b4d
sources:
- https://github.com/ziglang/zig
tasks:
- build: cd zig && ./ci/srht/update_download_page $VERSION
EOF
jq <$YML_FILE -sR '{
"manifest": .,
}' | curl \
-H Authorization:"token $OAUTH_TOKEN" \
-H Content-Type:application/json \
-X POST \
-d @- "https://builds.sr.ht/api/jobs"
+79
View File
@@ -0,0 +1,79 @@
#!/bin/sh
set -x
set -e
VERSION="$1"
SRCDIR="$(pwd)"
NATIVE_TARBALL="zig-linux-$(uname -m)-$VERSION.tar.xz"
# Check for all the builds being completed. It's expected that this script is run several times
# before they are all complete.
AARCH64_LINUX_JSON_URL="https://ziglang.org/builds/aarch64-linux-$VERSION.json"
X86_64_LINUX_JSON_URL="https://ziglang.org/builds/x86_64-linux-$VERSION.json"
X86_64_WINDOWS_JSON_URL="https://ziglang.org/builds/x86_64-windows-$VERSION.json"
X86_64_MACOS_JSON_URL="https://ziglang.org/builds/x86_64-macos-$VERSION.json"
X86_64_FREEBSD_JSON_URL="https://ziglang.org/builds/x86_64-freebsd-$VERSION.json"
# If any of these fail, it's not really this job failing; rather we have detected
# that this job will be called again later when other jobs have completed.
curl --fail -I "$AARCH64_LINUX_JSON_URL" >/dev/null || exit 0
curl --fail -I "$X86_64_LINUX_JSON_URL" >/dev/null || exit 0
curl --fail -I "$X86_64_WINDOWS_JSON_URL" >/dev/null || exit 0
curl --fail -I "$X86_64_MACOS_JSON_URL" >/dev/null || exit 0
curl --fail -I "$X86_64_FREEBSD_JSON_URL" >/dev/null || exit 0
# Without --user, this gave me:
# ERROR: Could not install packages due to an EnvironmentError: [Errno 13] Permission denied
pip3 install s3cmd --user
S3CMD="$HOME/.local/bin/s3cmd"
rm -rf .git
cd "$HOME"
wget "https://ziglang.org/builds/$NATIVE_TARBALL"
tar xf "$NATIVE_TARBALL"
ZIGDIR=$(basename $NATIVE_TARBALL .tar.xz)
ZIG="$ZIGDIR/zig"
LANGREF="$ZIGDIR/langref.html"
SRCTARBALLDIR="zig-$VERSION"
export SRC_TARBALL="$SRCTARBALLDIR.tar.xz"
mv "$SRCDIR" "$SRCTARBALLDIR"
tar cfJ "$SRC_TARBALL" "$SRCTARBALLDIR"
export SRC_SHASUM=$(sha256sum $SRC_TARBALL | cut '-d ' -f1)
export SRC_BYTESIZE=$(wc -c < $SRC_TARBALL)
X86_64_WINDOWS_JSON=$(curl --fail "$X86_64_WINDOWS_JSON_URL" || exit 1)
export X86_64_WINDOWS_TARBALL="$(echo "$X86_64_WINDOWS_JSON" | jq .tarball -r)"
export X86_64_WINDOWS_BYTESIZE="$(echo "$X86_64_WINDOWS_JSON" | jq .size -r)"
export X86_64_WINDOWS_SHASUM="$(echo "$X86_64_WINDOWS_JSON" | jq .shasum -r)"
X86_64_MACOS_JSON=$(curl --fail "$X86_64_MACOS_JSON_URL" || exit 1)
export X86_64_MACOS_TARBALL="$(echo "$X86_64_MACOS_JSON" | jq .tarball -r)"
export X86_64_MACOS_BYTESIZE="$(echo "$X86_64_MACOS_JSON" | jq .size -r)"
export X86_64_MACOS_SHASUM="$(echo "$X86_64_MACOS_JSON" | jq .shasum -r)"
X86_64_LINUX_JSON=$(curl --fail "$X86_64_LINUX_JSON_URL" || exit 1)
export X86_64_LINUX_TARBALL="$(echo "$X86_64_LINUX_JSON" | jq .tarball -r)"
export X86_64_LINUX_BYTESIZE="$(echo "$X86_64_LINUX_JSON" | jq .size -r)"
export X86_64_LINUX_SHASUM="$(echo "$X86_64_LINUX_JSON" | jq .shasum -r)"
AARCH64_LINUX_JSON=$(curl --fail "$AARCH64_LINUX_JSON_URL" || exit 1)
export AARCH64_LINUX_TARBALL="$(echo "$AARCH64_LINUX_JSON" | jq .tarball -r)"
export AARCH64_LINUX_BYTESIZE="$(echo "$AARCH64_LINUX_JSON" | jq .size -r)"
export AARCH64_LINUX_SHASUM="$(echo "$AARCH64_LINUX_JSON" | jq .shasum -r)"
X86_64_FREEBSD_JSON=$(curl --fail "$X86_64_FREEBSD_JSON_URL" || exit 1)
export X86_64_FREEBSD_TARBALL="$(echo "$X86_64_FREEBSD_JSON" | jq .tarball -r)"
export X86_64_FREEBSD_BYTESIZE="$(echo "$X86_64_FREEBSD_JSON" | jq .size -r)"
export X86_64_FREEBSD_SHASUM="$(echo "$X86_64_FREEBSD_JSON" | jq .shasum -r)"
git clone https://github.com/ziglang/www.ziglang.org --depth 1
cd www.ziglang.org
export MASTER_DATE="$(date +%Y-%m-%d)"
"../$ZIG" run update-download-page.zig
$S3CMD put -P --no-mime-magic --add-header="cache-control: public, max-age=31536000, immutable" "../$SRC_TARBALL" s3://ziglang.org/builds/
$S3CMD put -P --no-mime-magic "../$LANGREF" s3://ziglang.org/documentation/master/index.html --add-header="Cache-Control: max-age=0, must-revalidate"
$S3CMD put -P --no-mime-magic www/download/index.html s3://ziglang.org/download/index.html --add-header="Cache-Control: max-age=0, must-revalidate"
$S3CMD put -P --no-mime-magic www/download/index.json s3://ziglang.org/download/index.json --add-header="Cache-Control: max-age=0, must-revalidate"
+13
View File
@@ -0,0 +1,13 @@
if(MSVC)
set(CMAKE_C_FLAGS_DEBUG_INIT
"/D_DEBUG /MTd /Zi /Ob0 /Od /RTC1")
set(CMAKE_C_FLAGS_MINSIZEREL_INIT
"/MT /O1 /Ob1 /D NDEBUG")
set(CMAKE_C_FLAGS_RELEASE_INIT
"/MT /O2 /Ob1 /D NDEBUG")
set(CMAKE_C_FLAGS_RELWITHDEBINFO_INIT
"/MT /Zi /O2 /Ob1 /D NDEBUG")
endif()
+13
View File
@@ -0,0 +1,13 @@
if(MSVC)
set(CMAKE_CXX_FLAGS_DEBUG_INIT
"/D_DEBUG /MTd /Zi /Ob0 /Od /RTC1")
set(CMAKE_CXX_FLAGS_MINSIZEREL_INIT
"/MT /O1 /Ob1 /D NDEBUG")
set(CMAKE_CXX_FLAGS_RELEASE_INIT
"/MT /O2 /Ob1 /D NDEBUG")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT
"/MT /Zi /O2 /Ob1 /D NDEBUG")
endif()
+171 -162
View File
@@ -10,13 +10,13 @@ const testing = std.testing;
const max_doc_file_size = 10 * 1024 * 1024;
const exe_ext = std.build.Target(std.build.Target.Native).exeFileExt();
const obj_ext = std.build.Target(std.build.Target.Native).oFileExt();
const exe_ext = @as(std.build.Target, std.build.Target.Native).exeFileExt();
const obj_ext = @as(std.build.Target, std.build.Target.Native).oFileExt();
const tmp_dir_name = "docgen_tmp";
const test_out_path = tmp_dir_name ++ fs.path.sep_str ++ "test" ++ exe_ext;
pub fn main() !void {
var arena = std.heap.ArenaAllocator.init(std.heap.direct_allocator);
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer arena.deinit();
const allocator = &arena.allocator;
@@ -51,7 +51,7 @@ pub fn main() !void {
var toc = try genToc(allocator, &tokenizer);
try fs.makePath(allocator, tmp_dir_name);
defer fs.deleteTree(allocator, tmp_dir_name) catch {};
defer fs.deleteTree(tmp_dir_name) catch {};
try genHtml(allocator, &tokenizer, &toc, &buffered_out_stream.stream, zig_exe);
try buffered_out_stream.flush();
@@ -215,32 +215,33 @@ const Tokenizer = struct {
}
};
fn parseError(tokenizer: *Tokenizer, token: Token, comptime fmt: []const u8, args: ...) anyerror {
fn parseError(tokenizer: *Tokenizer, token: Token, comptime fmt: []const u8, args: var) anyerror {
const loc = tokenizer.getTokenLocation(token);
warn("{}:{}:{}: error: " ++ fmt ++ "\n", tokenizer.source_file_name, loc.line + 1, loc.column + 1, args);
const args_prefix = .{ tokenizer.source_file_name, loc.line + 1, loc.column + 1 };
warn("{}:{}:{}: error: " ++ fmt ++ "\n", args_prefix ++ args);
if (loc.line_start <= loc.line_end) {
warn("{}\n", tokenizer.buffer[loc.line_start..loc.line_end]);
warn("{}\n", .{tokenizer.buffer[loc.line_start..loc.line_end]});
{
var i: usize = 0;
while (i < loc.column) : (i += 1) {
warn(" ");
warn(" ", .{});
}
}
{
const caret_count = token.end - token.start;
var i: usize = 0;
while (i < caret_count) : (i += 1) {
warn("~");
warn("~", .{});
}
}
warn("\n");
warn("\n", .{});
}
return error.ParseError;
}
fn assertToken(tokenizer: *Tokenizer, token: Token, id: Token.Id) !void {
if (token.id != id) {
return parseError(tokenizer, token, "expected {}, found {}", @tagName(id), @tagName(token.id));
return parseError(tokenizer, token, "expected {}, found {}", .{ @tagName(id), @tagName(token.id) });
}
}
@@ -339,7 +340,7 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc {
switch (token.id) {
Token.Id.Eof => {
if (header_stack_size != 0) {
return parseError(tokenizer, token, "unbalanced headers");
return parseError(tokenizer, token, "unbalanced headers", .{});
}
try toc.write(" </ul>\n");
break;
@@ -370,13 +371,18 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc {
.Separator => continue,
.TagContent => {
const param = tokenizer.buffer[bracket_tok.start..bracket_tok.end];
if (mem.eql(u8, param, "3col")) {
columns = 3;
if (mem.eql(u8, param, "2col")) {
columns = 2;
} else {
return parseError(tokenizer, bracket_tok, "unrecognized header_open param: {}", param);
return parseError(
tokenizer,
bracket_tok,
"unrecognized header_open param: {}",
.{param},
);
}
},
else => return parseError(tokenizer, bracket_tok, "invalid header_open token"),
else => return parseError(tokenizer, bracket_tok, "invalid header_open token", .{}),
}
}
@@ -391,15 +397,15 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc {
},
});
if (try urls.put(urlized, tag_token)) |entry| {
parseError(tokenizer, tag_token, "duplicate header url: #{}", urlized) catch {};
parseError(tokenizer, entry.value, "other tag here") catch {};
parseError(tokenizer, tag_token, "duplicate header url: #{}", .{urlized}) catch {};
parseError(tokenizer, entry.value, "other tag here", .{}) catch {};
return error.ParseError;
}
if (last_action == Action.Open) {
try toc.writeByte('\n');
try toc.writeByteNTimes(' ', header_stack_size * 4);
if (last_columns) |n| {
try toc.print("<ul style=\"columns: {}\">\n", n);
try toc.print("<ul style=\"columns: {}\">\n", .{n});
} else {
try toc.write("<ul>\n");
}
@@ -408,10 +414,10 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc {
}
last_columns = columns;
try toc.writeByteNTimes(' ', 4 + header_stack_size * 4);
try toc.print("<li><a id=\"toc-{}\" href=\"#{}\">{}</a>", urlized, urlized, content);
try toc.print("<li><a id=\"toc-{}\" href=\"#{}\">{}</a>", .{ urlized, urlized, content });
} else if (mem.eql(u8, tag_name, "header_close")) {
if (header_stack_size == 0) {
return parseError(tokenizer, tag_token, "unbalanced close header");
return parseError(tokenizer, tag_token, "unbalanced close header", .{});
}
header_stack_size -= 1;
_ = try eatToken(tokenizer, Token.Id.BracketClose);
@@ -442,7 +448,7 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc {
try nodes.append(Node{ .SeeAlso = list.toOwnedSlice() });
break;
},
else => return parseError(tokenizer, see_also_tok, "invalid see_also token"),
else => return parseError(tokenizer, see_also_tok, "invalid see_also token", .{}),
}
}
} else if (mem.eql(u8, tag_name, "link")) {
@@ -459,7 +465,7 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc {
_ = try eatToken(tokenizer, Token.Id.BracketClose);
break :blk tokenizer.buffer[explicit_text.start..explicit_text.end];
},
else => return parseError(tokenizer, tok, "invalid link token"),
else => return parseError(tokenizer, tok, "invalid link token", .{}),
}
};
@@ -482,7 +488,7 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc {
_ = try eatToken(tokenizer, Token.Id.BracketClose);
},
Token.Id.BracketClose => {},
else => return parseError(tokenizer, token, "invalid token"),
else => return parseError(tokenizer, token, "invalid token", .{}),
}
const code_kind_str = tokenizer.buffer[code_kind_tok.start..code_kind_tok.end];
var code_kind_id: Code.Id = undefined;
@@ -512,7 +518,7 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc {
code_kind_id = Code.Id{ .Obj = null };
is_inline = true;
} else {
return parseError(tokenizer, code_kind_tok, "unrecognized code kind: {}", code_kind_str);
return parseError(tokenizer, code_kind_tok, "unrecognized code kind: {}", .{code_kind_str});
}
var mode = builtin.Mode.Debug;
@@ -550,7 +556,12 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc {
_ = try eatToken(tokenizer, Token.Id.BracketClose);
break content_tok;
} else {
return parseError(tokenizer, end_code_tag, "invalid token inside code_begin: {}", end_tag_name);
return parseError(
tokenizer,
end_code_tag,
"invalid token inside code_begin: {}",
.{end_tag_name},
);
}
_ = try eatToken(tokenizer, Token.Id.BracketClose);
} else
@@ -575,15 +586,20 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc {
const end_syntax_tag = try eatToken(tokenizer, Token.Id.TagContent);
const end_tag_name = tokenizer.buffer[end_syntax_tag.start..end_syntax_tag.end];
if (!mem.eql(u8, end_tag_name, "endsyntax")) {
return parseError(tokenizer, end_syntax_tag, "invalid token inside syntax: {}", end_tag_name);
return parseError(
tokenizer,
end_syntax_tag,
"invalid token inside syntax: {}",
.{end_tag_name},
);
}
_ = try eatToken(tokenizer, Token.Id.BracketClose);
try nodes.append(Node{ .Syntax = content_tok });
} else {
return parseError(tokenizer, tag_token, "unrecognized tag name: {}", tag_name);
return parseError(tokenizer, tag_token, "unrecognized tag name: {}", .{tag_name});
}
},
else => return parseError(tokenizer, token, "invalid token"),
else => return parseError(tokenizer, token, "invalid token", .{}),
}
}
@@ -729,7 +745,7 @@ fn termColor(allocator: *mem.Allocator, input: []const u8) ![]u8 {
try out.write("</span>");
}
if (first_number != 0 or second_number != 0) {
try out.print("<span class=\"t{}_{}\">", first_number, second_number);
try out.print("<span class=\"t{}_{}\">", .{ first_number, second_number });
open_span_count += 1;
}
},
@@ -802,6 +818,7 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok
.Keyword_resume,
.Keyword_return,
.Keyword_linksection,
.Keyword_callconv,
.Keyword_stdcallcc,
.Keyword_struct,
.Keyword_suspend,
@@ -856,6 +873,7 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok
.LineComment,
.DocComment,
.ContainerDocComment,
.ShebangLine,
=> {
try out.write("<span class=\"tok-comment\">");
@@ -917,6 +935,7 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok
.LBracket,
.RBracket,
.Period,
.PeriodAsterisk,
.Ellipsis2,
.Ellipsis3,
.Caret,
@@ -952,14 +971,13 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok
.AngleBracketAngleBracketRight,
.AngleBracketAngleBracketRightEqual,
.Tilde,
.BracketStarBracket,
.BracketStarCBracket,
=> try writeEscaped(out, src[token.start..token.end]),
.Invalid, .Invalid_ampersands => return parseError(
docgen_tokenizer,
source_token,
"syntax error",
.{},
),
}
index = token.end;
@@ -987,9 +1005,9 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
},
Node.Link => |info| {
if (!toc.urls.contains(info.url)) {
return parseError(tokenizer, info.token, "url not found: {}", info.url);
return parseError(tokenizer, info.token, "url not found: {}", .{info.url});
}
try out.print("<a href=\"#{}\">{}</a>", info.url, info.name);
try out.print("<a href=\"#{}\">{}</a>", .{ info.url, info.name });
},
Node.Nav => {
try out.write(toc.toc);
@@ -1002,12 +1020,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
Node.HeaderOpen => |info| {
try out.print(
"<h{} id=\"{}\"><a href=\"#toc-{}\">{}</a> <a class=\"hdr\" href=\"#{}\">§</a></h{}>\n",
info.n,
info.url,
info.url,
info.name,
info.url,
info.n,
.{ info.n, info.url, info.url, info.name, info.url, info.n },
);
},
Node.SeeAlso => |items| {
@@ -1015,9 +1028,9 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
for (items) |item| {
const url = try urlize(allocator, item.name);
if (!toc.urls.contains(url)) {
return parseError(tokenizer, item.token, "url not found: {}", url);
return parseError(tokenizer, item.token, "url not found: {}", .{url});
}
try out.print("<li><a href=\"#{}\">{}</a></li>\n", url, item.name);
try out.print("<li><a href=\"#{}\">{}</a></li>\n", .{ url, item.name });
}
try out.write("</ul>\n");
},
@@ -1026,29 +1039,29 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
},
Node.Code => |code| {
code_progress_index += 1;
warn("docgen example code {}/{}...", code_progress_index, tokenizer.code_node_count);
warn("docgen example code {}/{}...", .{ code_progress_index, tokenizer.code_node_count });
const raw_source = tokenizer.buffer[code.source_token.start..code.source_token.end];
const trimmed_raw_source = mem.trim(u8, raw_source, " \n");
if (!code.is_inline) {
try out.print("<p class=\"file\">{}.zig</p>", code.name);
try out.print("<p class=\"file\">{}.zig</p>", .{code.name});
}
try out.write("<pre>");
try tokenizeAndPrint(tokenizer, out, code.source_token);
try out.write("</pre>");
const name_plus_ext = try std.fmt.allocPrint(allocator, "{}.zig", code.name);
const name_plus_ext = try std.fmt.allocPrint(allocator, "{}.zig", .{code.name});
const tmp_source_file_name = try fs.path.join(
allocator,
[_][]const u8{ tmp_dir_name, name_plus_ext },
&[_][]const u8{ tmp_dir_name, name_plus_ext },
);
try io.writeFile(tmp_source_file_name, trimmed_raw_source);
switch (code.id) {
Code.Id.Exe => |expected_outcome| code_block: {
const name_plus_bin_ext = try std.fmt.allocPrint(allocator, "{}{}", code.name, exe_ext);
const name_plus_bin_ext = try std.fmt.allocPrint(allocator, "{}{}", .{ code.name, exe_ext });
var build_args = std.ArrayList([]const u8).init(allocator);
defer build_args.deinit();
try build_args.appendSlice([_][]const u8{
try build_args.appendSlice(&[_][]const u8{
zig_exe,
"build-exe",
tmp_source_file_name,
@@ -1059,40 +1072,40 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
"--cache",
"on",
});
try out.print("<pre><code class=\"shell\">$ zig build-exe {}.zig", code.name);
try out.print("<pre><code class=\"shell\">$ zig build-exe {}.zig", .{code.name});
switch (code.mode) {
builtin.Mode.Debug => {},
builtin.Mode.ReleaseSafe => {
try build_args.append("--release-safe");
try out.print(" --release-safe");
try out.print(" --release-safe", .{});
},
builtin.Mode.ReleaseFast => {
try build_args.append("--release-fast");
try out.print(" --release-fast");
try out.print(" --release-fast", .{});
},
builtin.Mode.ReleaseSmall => {
try build_args.append("--release-small");
try out.print(" --release-small");
try out.print(" --release-small", .{});
},
}
for (code.link_objects) |link_object| {
const name_with_ext = try std.fmt.allocPrint(allocator, "{}{}", link_object, obj_ext);
const name_with_ext = try std.fmt.allocPrint(allocator, "{}{}", .{ link_object, obj_ext });
const full_path_object = try fs.path.join(
allocator,
[_][]const u8{ tmp_dir_name, name_with_ext },
&[_][]const u8{ tmp_dir_name, name_with_ext },
);
try build_args.append("--object");
try build_args.append(full_path_object);
try out.print(" --object {}", name_with_ext);
try out.print(" --object {}", .{name_with_ext});
}
if (code.link_libc) {
try build_args.append("-lc");
try out.print(" -lc");
try out.print(" -lc", .{});
}
if (code.target_str) |triple| {
try build_args.appendSlice([_][]const u8{ "-target", triple });
try build_args.appendSlice(&[_][]const u8{ "-target", triple });
if (!code.is_inline) {
try out.print(" -target {}", triple);
try out.print(" -target {}", .{triple});
}
}
if (expected_outcome == .BuildFail) {
@@ -1106,29 +1119,29 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
switch (result.term) {
.Exited => |exit_code| {
if (exit_code == 0) {
warn("{}\nThe following command incorrectly succeeded:\n", result.stderr);
warn("{}\nThe following command incorrectly succeeded:\n", .{result.stderr});
for (build_args.toSliceConst()) |arg|
warn("{} ", arg)
warn("{} ", .{arg})
else
warn("\n");
return parseError(tokenizer, code.source_token, "example incorrectly compiled");
warn("\n", .{});
return parseError(tokenizer, code.source_token, "example incorrectly compiled", .{});
}
},
else => {
warn("{}\nThe following command crashed:\n", result.stderr);
warn("{}\nThe following command crashed:\n", .{result.stderr});
for (build_args.toSliceConst()) |arg|
warn("{} ", arg)
warn("{} ", .{arg})
else
warn("\n");
return parseError(tokenizer, code.source_token, "example compile crashed");
warn("\n", .{});
return parseError(tokenizer, code.source_token, "example compile crashed", .{});
},
}
const escaped_stderr = try escapeHtml(allocator, result.stderr);
const colored_stderr = try termColor(allocator, escaped_stderr);
try out.print("\n{}</code></pre>\n", colored_stderr);
try out.print("\n{}</code></pre>\n", .{colored_stderr});
break :code_block;
}
const exec_result = exec(allocator, &env_map, build_args.toSliceConst()) catch return parseError(tokenizer, code.source_token, "example failed to compile");
const exec_result = exec(allocator, &env_map, build_args.toSliceConst()) catch return parseError(tokenizer, code.source_token, "example failed to compile", .{});
if (code.target_str) |triple| {
if (mem.startsWith(u8, triple, "wasm32") or
@@ -1137,13 +1150,13 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
(builtin.os != .linux or builtin.arch != .x86_64))
{
// skip execution
try out.print("</code></pre>\n");
try out.print("</code></pre>\n", .{});
break :code_block;
}
}
const path_to_exe = mem.trim(u8, exec_result.stdout, " \r\n");
const run_args = [_][]const u8{path_to_exe};
const run_args = &[_][]const u8{path_to_exe};
var exited_with_signal = false;
@@ -1152,12 +1165,12 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
switch (result.term) {
.Exited => |exit_code| {
if (exit_code == 0) {
warn("{}\nThe following command incorrectly succeeded:\n", result.stderr);
warn("{}\nThe following command incorrectly succeeded:\n", .{result.stderr});
for (run_args) |arg|
warn("{} ", arg)
warn("{} ", .{arg})
else
warn("\n");
return parseError(tokenizer, code.source_token, "example incorrectly compiled");
warn("\n", .{});
return parseError(tokenizer, code.source_token, "example incorrectly compiled", .{});
}
},
.Signal => exited_with_signal = true,
@@ -1165,7 +1178,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
}
break :blk result;
} else blk: {
break :blk exec(allocator, &env_map, run_args) catch return parseError(tokenizer, code.source_token, "example crashed");
break :blk exec(allocator, &env_map, run_args) catch return parseError(tokenizer, code.source_token, "example crashed", .{});
};
const escaped_stderr = try escapeHtml(allocator, result.stderr);
@@ -1174,57 +1187,57 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
const colored_stderr = try termColor(allocator, escaped_stderr);
const colored_stdout = try termColor(allocator, escaped_stdout);
try out.print("\n$ ./{}\n{}{}", code.name, colored_stdout, colored_stderr);
try out.print("\n$ ./{}\n{}{}", .{ code.name, colored_stdout, colored_stderr });
if (exited_with_signal) {
try out.print("(process terminated by signal)");
try out.print("(process terminated by signal)", .{});
}
try out.print("</code></pre>\n");
try out.print("</code></pre>\n", .{});
},
Code.Id.Test => {
var test_args = std.ArrayList([]const u8).init(allocator);
defer test_args.deinit();
try test_args.appendSlice([_][]const u8{
try test_args.appendSlice(&[_][]const u8{
zig_exe,
"test",
tmp_source_file_name,
"--cache",
"on",
});
try out.print("<pre><code class=\"shell\">$ zig test {}.zig", code.name);
try out.print("<pre><code class=\"shell\">$ zig test {}.zig", .{code.name});
switch (code.mode) {
builtin.Mode.Debug => {},
builtin.Mode.ReleaseSafe => {
try test_args.append("--release-safe");
try out.print(" --release-safe");
try out.print(" --release-safe", .{});
},
builtin.Mode.ReleaseFast => {
try test_args.append("--release-fast");
try out.print(" --release-fast");
try out.print(" --release-fast", .{});
},
builtin.Mode.ReleaseSmall => {
try test_args.append("--release-small");
try out.print(" --release-small");
try out.print(" --release-small", .{});
},
}
if (code.link_libc) {
try test_args.append("-lc");
try out.print(" -lc");
try out.print(" -lc", .{});
}
if (code.target_str) |triple| {
try test_args.appendSlice([_][]const u8{ "-target", triple });
try out.print(" -target {}", triple);
try test_args.appendSlice(&[_][]const u8{ "-target", triple });
try out.print(" -target {}", .{triple});
}
const result = exec(allocator, &env_map, test_args.toSliceConst()) catch return parseError(tokenizer, code.source_token, "test failed");
const result = exec(allocator, &env_map, test_args.toSliceConst()) catch return parseError(tokenizer, code.source_token, "test failed", .{});
const escaped_stderr = try escapeHtml(allocator, result.stderr);
const escaped_stdout = try escapeHtml(allocator, result.stdout);
try out.print("\n{}{}</code></pre>\n", escaped_stderr, escaped_stdout);
try out.print("\n{}{}</code></pre>\n", .{ escaped_stderr, escaped_stdout });
},
Code.Id.TestError => |error_match| {
var test_args = std.ArrayList([]const u8).init(allocator);
defer test_args.deinit();
try test_args.appendSlice([_][]const u8{
try test_args.appendSlice(&[_][]const u8{
zig_exe,
"test",
"--color",
@@ -1233,57 +1246,57 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
"--output-dir",
tmp_dir_name,
});
try out.print("<pre><code class=\"shell\">$ zig test {}.zig", code.name);
try out.print("<pre><code class=\"shell\">$ zig test {}.zig", .{code.name});
switch (code.mode) {
builtin.Mode.Debug => {},
builtin.Mode.ReleaseSafe => {
try test_args.append("--release-safe");
try out.print(" --release-safe");
try out.print(" --release-safe", .{});
},
builtin.Mode.ReleaseFast => {
try test_args.append("--release-fast");
try out.print(" --release-fast");
try out.print(" --release-fast", .{});
},
builtin.Mode.ReleaseSmall => {
try test_args.append("--release-small");
try out.print(" --release-small");
try out.print(" --release-small", .{});
},
}
const result = try ChildProcess.exec(allocator, test_args.toSliceConst(), null, &env_map, max_doc_file_size);
switch (result.term) {
.Exited => |exit_code| {
if (exit_code == 0) {
warn("{}\nThe following command incorrectly succeeded:\n", result.stderr);
warn("{}\nThe following command incorrectly succeeded:\n", .{result.stderr});
for (test_args.toSliceConst()) |arg|
warn("{} ", arg)
warn("{} ", .{arg})
else
warn("\n");
return parseError(tokenizer, code.source_token, "example incorrectly compiled");
warn("\n", .{});
return parseError(tokenizer, code.source_token, "example incorrectly compiled", .{});
}
},
else => {
warn("{}\nThe following command crashed:\n", result.stderr);
warn("{}\nThe following command crashed:\n", .{result.stderr});
for (test_args.toSliceConst()) |arg|
warn("{} ", arg)
warn("{} ", .{arg})
else
warn("\n");
return parseError(tokenizer, code.source_token, "example compile crashed");
warn("\n", .{});
return parseError(tokenizer, code.source_token, "example compile crashed", .{});
},
}
if (mem.indexOf(u8, result.stderr, error_match) == null) {
warn("{}\nExpected to find '{}' in stderr", result.stderr, error_match);
return parseError(tokenizer, code.source_token, "example did not have expected compile error");
warn("{}\nExpected to find '{}' in stderr", .{ result.stderr, error_match });
return parseError(tokenizer, code.source_token, "example did not have expected compile error", .{});
}
const escaped_stderr = try escapeHtml(allocator, result.stderr);
const colored_stderr = try termColor(allocator, escaped_stderr);
try out.print("\n{}</code></pre>\n", colored_stderr);
try out.print("\n{}</code></pre>\n", .{colored_stderr});
},
Code.Id.TestSafety => |error_match| {
var test_args = std.ArrayList([]const u8).init(allocator);
defer test_args.deinit();
try test_args.appendSlice([_][]const u8{
try test_args.appendSlice(&[_][]const u8{
zig_exe,
"test",
tmp_source_file_name,
@@ -1311,52 +1324,51 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
switch (result.term) {
.Exited => |exit_code| {
if (exit_code == 0) {
warn("{}\nThe following command incorrectly succeeded:\n", result.stderr);
warn("{}\nThe following command incorrectly succeeded:\n", .{result.stderr});
for (test_args.toSliceConst()) |arg|
warn("{} ", arg)
warn("{} ", .{arg})
else
warn("\n");
return parseError(tokenizer, code.source_token, "example test incorrectly succeeded");
warn("\n", .{});
return parseError(tokenizer, code.source_token, "example test incorrectly succeeded", .{});
}
},
else => {
warn("{}\nThe following command crashed:\n", result.stderr);
warn("{}\nThe following command crashed:\n", .{result.stderr});
for (test_args.toSliceConst()) |arg|
warn("{} ", arg)
warn("{} ", .{arg})
else
warn("\n");
return parseError(tokenizer, code.source_token, "example compile crashed");
warn("\n", .{});
return parseError(tokenizer, code.source_token, "example compile crashed", .{});
},
}
if (mem.indexOf(u8, result.stderr, error_match) == null) {
warn("{}\nExpected to find '{}' in stderr", result.stderr, error_match);
return parseError(tokenizer, code.source_token, "example did not have expected runtime safety error message");
warn("{}\nExpected to find '{}' in stderr", .{ result.stderr, error_match });
return parseError(tokenizer, code.source_token, "example did not have expected runtime safety error message", .{});
}
const escaped_stderr = try escapeHtml(allocator, result.stderr);
const colored_stderr = try termColor(allocator, escaped_stderr);
try out.print(
"<pre><code class=\"shell\">$ zig test {}.zig{}\n{}</code></pre>\n",
try out.print("<pre><code class=\"shell\">$ zig test {}.zig{}\n{}</code></pre>\n", .{
code.name,
mode_arg,
colored_stderr,
);
});
},
Code.Id.Obj => |maybe_error_match| {
const name_plus_obj_ext = try std.fmt.allocPrint(allocator, "{}{}", code.name, obj_ext);
const name_plus_obj_ext = try std.fmt.allocPrint(allocator, "{}{}", .{ code.name, obj_ext });
const tmp_obj_file_name = try fs.path.join(
allocator,
[_][]const u8{ tmp_dir_name, name_plus_obj_ext },
&[_][]const u8{ tmp_dir_name, name_plus_obj_ext },
);
var build_args = std.ArrayList([]const u8).init(allocator);
defer build_args.deinit();
const name_plus_h_ext = try std.fmt.allocPrint(allocator, "{}.h", code.name);
const name_plus_h_ext = try std.fmt.allocPrint(allocator, "{}.h", .{code.name});
const output_h_file_name = try fs.path.join(
allocator,
[_][]const u8{ tmp_dir_name, name_plus_h_ext },
&[_][]const u8{ tmp_dir_name, name_plus_h_ext },
);
try build_args.appendSlice([_][]const u8{
try build_args.appendSlice(&[_][]const u8{
zig_exe,
"build-obj",
tmp_source_file_name,
@@ -1369,7 +1381,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
});
if (!code.is_inline) {
try out.print("<pre><code class=\"shell\">$ zig build-obj {}.zig", code.name);
try out.print("<pre><code class=\"shell\">$ zig build-obj {}.zig", .{code.name});
}
switch (code.mode) {
@@ -1377,26 +1389,26 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
builtin.Mode.ReleaseSafe => {
try build_args.append("--release-safe");
if (!code.is_inline) {
try out.print(" --release-safe");
try out.print(" --release-safe", .{});
}
},
builtin.Mode.ReleaseFast => {
try build_args.append("--release-fast");
if (!code.is_inline) {
try out.print(" --release-fast");
try out.print(" --release-fast", .{});
}
},
builtin.Mode.ReleaseSmall => {
try build_args.append("--release-small");
if (!code.is_inline) {
try out.print(" --release-small");
try out.print(" --release-small", .{});
}
},
}
if (code.target_str) |triple| {
try build_args.appendSlice([_][]const u8{ "-target", triple });
try out.print(" -target {}", triple);
try build_args.appendSlice(&[_][]const u8{ "-target", triple });
try out.print(" -target {}", .{triple});
}
if (maybe_error_match) |error_match| {
@@ -1404,78 +1416,75 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
switch (result.term) {
.Exited => |exit_code| {
if (exit_code == 0) {
warn("{}\nThe following command incorrectly succeeded:\n", result.stderr);
warn("{}\nThe following command incorrectly succeeded:\n", .{result.stderr});
for (build_args.toSliceConst()) |arg|
warn("{} ", arg)
warn("{} ", .{arg})
else
warn("\n");
return parseError(tokenizer, code.source_token, "example build incorrectly succeeded");
warn("\n", .{});
return parseError(tokenizer, code.source_token, "example build incorrectly succeeded", .{});
}
},
else => {
warn("{}\nThe following command crashed:\n", result.stderr);
warn("{}\nThe following command crashed:\n", .{result.stderr});
for (build_args.toSliceConst()) |arg|
warn("{} ", arg)
warn("{} ", .{arg})
else
warn("\n");
return parseError(tokenizer, code.source_token, "example compile crashed");
warn("\n", .{});
return parseError(tokenizer, code.source_token, "example compile crashed", .{});
},
}
if (mem.indexOf(u8, result.stderr, error_match) == null) {
warn("{}\nExpected to find '{}' in stderr", result.stderr, error_match);
return parseError(tokenizer, code.source_token, "example did not have expected compile error message");
warn("{}\nExpected to find '{}' in stderr", .{ result.stderr, error_match });
return parseError(tokenizer, code.source_token, "example did not have expected compile error message", .{});
}
const escaped_stderr = try escapeHtml(allocator, result.stderr);
const colored_stderr = try termColor(allocator, escaped_stderr);
try out.print("\n{}\n", colored_stderr);
if (!code.is_inline) {
try out.print("</code></pre>\n");
}
try out.print("\n{}", .{colored_stderr});
} else {
_ = exec(allocator, &env_map, build_args.toSliceConst()) catch return parseError(tokenizer, code.source_token, "example failed to compile");
_ = exec(allocator, &env_map, build_args.toSliceConst()) catch return parseError(tokenizer, code.source_token, "example failed to compile", .{});
}
if (!code.is_inline) {
try out.print("</code></pre>\n");
try out.print("</code></pre>\n", .{});
}
},
Code.Id.Lib => {
var test_args = std.ArrayList([]const u8).init(allocator);
defer test_args.deinit();
try test_args.appendSlice([_][]const u8{
try test_args.appendSlice(&[_][]const u8{
zig_exe,
"build-lib",
tmp_source_file_name,
"--output-dir",
tmp_dir_name,
});
try out.print("<pre><code class=\"shell\">$ zig build-lib {}.zig", code.name);
try out.print("<pre><code class=\"shell\">$ zig build-lib {}.zig", .{code.name});
switch (code.mode) {
builtin.Mode.Debug => {},
builtin.Mode.ReleaseSafe => {
try test_args.append("--release-safe");
try out.print(" --release-safe");
try out.print(" --release-safe", .{});
},
builtin.Mode.ReleaseFast => {
try test_args.append("--release-fast");
try out.print(" --release-fast");
try out.print(" --release-fast", .{});
},
builtin.Mode.ReleaseSmall => {
try test_args.append("--release-small");
try out.print(" --release-small");
try out.print(" --release-small", .{});
},
}
if (code.target_str) |triple| {
try test_args.appendSlice([_][]const u8{ "-target", triple });
try out.print(" -target {}", triple);
try test_args.appendSlice(&[_][]const u8{ "-target", triple });
try out.print(" -target {}", .{triple});
}
const result = exec(allocator, &env_map, test_args.toSliceConst()) catch return parseError(tokenizer, code.source_token, "test failed");
const result = exec(allocator, &env_map, test_args.toSliceConst()) catch return parseError(tokenizer, code.source_token, "test failed", .{});
const escaped_stderr = try escapeHtml(allocator, result.stderr);
const escaped_stdout = try escapeHtml(allocator, result.stdout);
try out.print("\n{}{}</code></pre>\n", escaped_stderr, escaped_stdout);
try out.print("\n{}{}</code></pre>\n", .{ escaped_stderr, escaped_stdout });
},
}
warn("OK\n");
warn("OK\n", .{});
},
}
}
@@ -1486,20 +1495,20 @@ fn exec(allocator: *mem.Allocator, env_map: *std.BufMap, args: []const []const u
switch (result.term) {
.Exited => |exit_code| {
if (exit_code != 0) {
warn("{}\nThe following command exited with code {}:\n", result.stderr, exit_code);
warn("{}\nThe following command exited with code {}:\n", .{ result.stderr, exit_code });
for (args) |arg|
warn("{} ", arg)
warn("{} ", .{arg})
else
warn("\n");
warn("\n", .{});
return error.ChildExitError;
}
},
else => {
warn("{}\nThe following command crashed:\n", result.stderr);
warn("{}\nThe following command crashed:\n", .{result.stderr});
for (args) |arg|
warn("{} ", arg)
warn("{} ", .{arg})
else
warn("\n");
warn("\n", .{});
return error.ChildCrashed;
},
}
@@ -1507,7 +1516,7 @@ fn exec(allocator: *mem.Allocator, env_map: *std.BufMap, args: []const []const u
}
fn getBuiltinCode(allocator: *mem.Allocator, env_map: *std.BufMap, zig_exe: []const u8) ![]const u8 {
const result = try exec(allocator, env_map, [_][]const u8{
const result = try exec(allocator, env_map, &[_][]const u8{
zig_exe,
"builtin",
});
+782 -664
View File
@@ -1,13 +1,13 @@
<!doctype html>
<html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
<title>Documentation - The Zig Programming Language</title>
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNSAxMCIgZmlsbD0iI2Y3YTQxZCI+PHBhdGggZD0iTTAsMSBIMy41IFYzIEgyIFY3IEgzLjY4MiBMMS44ODEsOSBIMCBaIE0xNSw5IEgxMS41IFY3IEgxMyBWMyBIMTEuMzE4IEwxMy4xMTksMSBIMTUgWiBNNCwxIEg5LjkxMiBMMTMuMzI4LDAuMDIxIEw3LjA0NSw3IEgxMSBWOSBINS4wODggTDEuNjcyLDkuOTc5IEw3Ljk1NSwzIEg0IFoiLz48L3N2Zz4="/>
<style type="text/css">
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg=="/>
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
}
a:not(:hover) {
text-decoration: none;
@@ -81,11 +81,35 @@
font-weight: bold;
}
#main-wrapper {
display: flex;
flex-direction: column;
height: 100vh;
}
#contents-wrapper {
flex-grow: 1;
padding: 0 2em;
}
#contents {
max-width: 60em;
margin: auto;
}
#index {
padding: 0 1em;
}
@media screen and (min-width: 1025px) {
#main-wrapper {
flex-direction: row;
}
#contents-wrapper, #index {
overflow: auto;
}
}
h1 a, h2 a, h3 a, h4 a, h5 a {
text-decoration: none;
color: #333;
@@ -156,24 +180,31 @@
</style>
</head>
<body>
<a href="https://ziglang.org/documentation/0.1.1">0.1.1</a> |
<a href="https://ziglang.org/documentation/0.2.0">0.2.0</a> |
<a href="https://ziglang.org/documentation/0.3.0">0.3.0</a> |
<a href="https://ziglang.org/documentation/0.4.0">0.4.0</a> |
<a href="https://ziglang.org/documentation/0.5.0">0.5.0</a> |
master
<div id="contents">
<div id="main-wrapper">
<div id="index">
<a href="https://ziglang.org/documentation/0.1.1">0.1.1</a> |
<a href="https://ziglang.org/documentation/0.2.0">0.2.0</a> |
<a href="https://ziglang.org/documentation/0.3.0">0.3.0</a> |
<a href="https://ziglang.org/documentation/0.4.0">0.4.0</a> |
<a href="https://ziglang.org/documentation/0.5.0">0.5.0</a> |
master
<h1>Index</h1>
{#nav#}
</div>
<div id="contents-wrapper"><div id="contents">
{#header_open|Introduction#}
<p>
Zig is a general-purpose programming language designed for <strong>robustness</strong>,
<strong>optimality</strong>, and <strong>maintainability</strong>.
Zig is a general-purpose programming language and toolchain for maintaining
<strong>robust</strong>, <strong>optimal</strong>, and <strong>reusable</strong> software.
</p>
<ul>
<li><strong>Robust</strong> - behavior is correct even for edge cases such as out of memory.</li>
<li><strong>Optimal</strong> - write programs the best way they can behave and perform.</li>
<li><strong>Maintainable</strong> - precisely communicate intent to the compiler and other programmers.
The language imposes a low overhead to reading code and is resilient to changing requirements
and environments.</li>
<li><strong>Reusable</strong> - the same code works in many environments which have different
constraints.</li>
<li><strong>Maintainable</strong> - precisely communicate intent to the compiler and
other programmers. The language imposes a low overhead to reading code and is
resilient to changing requirements and environments.</li>
</ul>
<p>
Often the most efficient way to learn something new is to see examples, so
@@ -193,21 +224,14 @@
</p>
{#header_close#}
{#header_open|Index#}
{#nav#}
{#header_close#}
{#header_open|Hello World#}
{#code_begin|exe|hello#}
const std = @import("std");
pub fn main() !void {
// If this program is run without stdout attached, exit with an error.
const stdout_file = try std.io.getStdOut();
// If this program encounters pipe failure when printing to stdout, exit
// with an error.
try stdout_file.write("Hello, world!\n");
const stdout = &std.io.getStdOut().outStream().stream;
try stdout.print("Hello, {}!\n", .{"world"});
}
{#code_end#}
<p>
@@ -219,7 +243,7 @@ pub fn main() !void {
const warn = @import("std").debug.warn;
pub fn main() void {
warn("Hello, world!\n");
warn("Hello, world!\n", .{});
}
{#code_end#}
<p>
@@ -291,41 +315,50 @@ const assert = std.debug.assert;
pub fn main() void {
// integers
const one_plus_one: i32 = 1 + 1;
warn("1 + 1 = {}\n", one_plus_one);
warn("1 + 1 = {}\n", .{one_plus_one});
// floats
const seven_div_three: f32 = 7.0 / 3.0;
warn("7.0 / 3.0 = {}\n", seven_div_three);
warn("7.0 / 3.0 = {}\n", .{seven_div_three});
// boolean
warn("{}\n{}\n{}\n",
warn("{}\n{}\n{}\n", .{
true and false,
true or false,
!true);
!true,
});
// optional
var optional_value: ?[]const u8 = null;
assert(optional_value == null);
warn("\noptional 1\ntype: {}\nvalue: {}\n",
@typeName(@typeOf(optional_value)), optional_value);
warn("\noptional 1\ntype: {}\nvalue: {}\n", .{
@typeName(@TypeOf(optional_value)),
optional_value,
});
optional_value = "hi";
assert(optional_value != null);
warn("\noptional 2\ntype: {}\nvalue: {}\n",
@typeName(@typeOf(optional_value)), optional_value);
warn("\noptional 2\ntype: {}\nvalue: {}\n", .{
@typeName(@TypeOf(optional_value)),
optional_value,
});
// error union
var number_or_error: anyerror!i32 = error.ArgNotFound;
warn("\nerror union 1\ntype: {}\nvalue: {}\n",
@typeName(@typeOf(number_or_error)), number_or_error);
warn("\nerror union 1\ntype: {}\nvalue: {}\n", .{
@typeName(@TypeOf(number_or_error)),
number_or_error,
});
number_or_error = 1234;
warn("\nerror union 2\ntype: {}\nvalue: {}\n",
@typeName(@typeOf(number_or_error)), number_or_error);
warn("\nerror union 2\ntype: {}\nvalue: {}\n", .{
@typeName(@TypeOf(number_or_error)),
number_or_error,
});
}
{#code_end#}
{#header_open|Primitive Types#}
@@ -513,7 +546,7 @@ pub fn main() void {
</div>
<p>
In addition to the integer types above, arbitrary bit-width integers can be referenced by using
an identifier of <code>i</code> or </code>u</code> followed by digits. For example, the identifier
an identifier of <code>i</code> or <code>u</code> followed by digits. For example, the identifier
{#syntax#}i7{#endsyntax#} refers to a signed 7-bit integer. The maximum allowed bit-width of an
integer type is {#syntax#}65535{#endsyntax#}.
</p>
@@ -548,32 +581,31 @@ pub fn main() void {
{#header_close#}
{#header_open|String Literals and Character Literals#}
<p>
String literals are UTF-8 encoded byte arrays.
String literals are single-item constant {#link|Pointers#} to null-terminated UTF-8 encoded byte arrays.
The type of string literals encodes both the length, and the fact that they are null-terminated,
and thus they can be {#link|coerced|Type Coercion#} to both {#link|Slices#} and
{#link|Null-Terminated Pointers|Sentinel-Terminated Pointers#}.
Dereferencing string literals converts them to {#link|Arrays#}.
</p>
<p>
Character literals have type {#syntax#}comptime_int{#endsyntax#}, the same as
{#link|Integer Literals#}. All {#link|Escape Sequences#} are valid in both string literals
and character literals. Once https://github.com/ziglang/zig/issues/2097 is implemented,
character literals will be allowed to have a single UTF-8 encoded codepoint.
and character literals.
</p>
{#code_begin|test#}
const assert = @import("std").debug.assert;
const mem = @import("std").mem;
test "string literals" {
// In Zig a string literal is an array of bytes.
const normal_bytes = "hello";
assert(@typeOf(normal_bytes) == [5]u8);
assert(normal_bytes.len == 5);
assert(normal_bytes[1] == 'e');
const bytes = "hello";
assert(@TypeOf(bytes) == *const [5:0]u8);
assert(bytes.len == 5);
assert(bytes[1] == 'e');
assert(bytes[5] == 0);
assert('e' == '\x65');
assert('\u{1f4a9}' == 128169);
assert('💯' == 128175);
assert(mem.eql(u8, "hello", "h\x65llo"));
// A C string literal is a null terminated pointer.
const null_terminated_bytes = c"hello";
assert(@typeOf(null_terminated_bytes) == [*]const u8);
assert(null_terminated_bytes[5] == 0);
}
{#code_end#}
{#see_also|Arrays|Zig Test|Source Encoding#}
@@ -643,23 +675,6 @@ const hello_world_in_c =
\\}
;
{#code_end#}
<p>
For a multiline C string literal, prepend <code>c</code> to each {#syntax#}\\{#endsyntax#}:
</p>
{#code_begin|syntax#}
const c_string_literal =
c\\#include <stdio.h>
c\\
c\\int main(int argc, char **argv) {
c\\ printf("hello world\n");
c\\ return 0;
c\\}
;
{#code_end#}
<p>
In this example the variable {#syntax#}c_string_literal{#endsyntax#} has type {#syntax#}[*]const u8{#endsyntax#} and
has a terminating null byte.
</p>
{#see_also|@embedFile#}
{#header_close#}
{#header_close#}
@@ -713,7 +728,7 @@ test "init with undefined" {
}
{#code_end#}
<p>
{#syntax#}undefined{#endsyntax#} can be {#link|implicitly cast|Implicit Casts#} to any type.
{#syntax#}undefined{#endsyntax#} can be {#link|coerced|Type Coercion#} to any type.
Once this happens, it is no longer possible to detect that the value is {#syntax#}undefined{#endsyntax#}.
{#syntax#}undefined{#endsyntax#} means the value could be anything, even something that is nonsense
according to the type. Translated into English, {#syntax#}undefined{#endsyntax#} means "Not a meaningful
@@ -898,7 +913,7 @@ fn divide(a: i32, b: i32) i32 {
</p>
<p>
Zig supports arbitrary bit-width integers, referenced by using
an identifier of <code>i</code> or </code>u</code> followed by digits. For example, the identifier
an identifier of <code>i</code> or <code>u</code> followed by digits. For example, the identifier
{#syntax#}i7{#endsyntax#} refers to a signed 7-bit integer. The maximum allowed bit-width of an
integer type is {#syntax#}65535{#endsyntax#}.
</p>
@@ -921,7 +936,7 @@ fn divide(a: i32, b: i32) i32 {
{#syntax#}f128{#endsyntax#}.
</p>
<p>
Float literals {#link|implicitly cast|Implicit Casts#} to any floating point type,
Float literals {#link|coerce|Type Coercion#} to any floating point type,
and to any {#link|integer|Integers#} type when there is no fractional component.
</p>
{#code_begin|syntax#}
@@ -951,7 +966,7 @@ const nan = std.math.nan(f128);
{#code_begin|obj|foo#}
{#code_release_fast#}
const builtin = @import("builtin");
const big = f64(1 << 40);
const big = @as(f64, 1 << 40);
export fn foo_strict(x: f64) f64 {
return x + big - big;
@@ -974,8 +989,8 @@ extern fn foo_optimized(x: f64) f64;
pub fn main() void {
const x = 0.001;
warn("optimized = {}\n", foo_optimized(x));
warn("strict = {}\n", foo_strict(x));
warn("optimized = {}\n", .{foo_optimized(x)});
warn("strict = {}\n", .{foo_strict(x)});
}
{#code_end#}
{#see_also|@setFloatMode|Division by Zero#}
@@ -1039,7 +1054,7 @@ a +%= b{#endsyntax#}</pre></td>
</ul>
</td>
<td>
<pre>{#syntax#}u32(std.math.maxInt(u32)) +% 1 == 0{#endsyntax#}</pre>
<pre>{#syntax#}@as(u32, std.math.maxInt(u32)) +% 1 == 0{#endsyntax#}</pre>
</td>
</tr>
<tr>
@@ -1078,7 +1093,7 @@ a -%= b{#endsyntax#}</pre></td>
</ul>
</td>
<td>
<pre>{#syntax#}u32(0) -% 1 == std.math.maxInt(u32){#endsyntax#}</pre>
<pre>{#syntax#}@as(u32, 0) -% 1 == std.math.maxInt(u32){#endsyntax#}</pre>
</td>
</tr>
<tr>
@@ -1113,7 +1128,7 @@ a -%= b{#endsyntax#}</pre></td>
</ul>
</td>
<td>
<pre>{#syntax#}-%i32(std.math.minInt(i32)) == std.math.minInt(i32){#endsyntax#}</pre>
<pre>{#syntax#}-%@as(i32, std.math.minInt(i32)) == std.math.minInt(i32){#endsyntax#}</pre>
</td>
</tr>
<tr>
@@ -1152,7 +1167,7 @@ a *%= b{#endsyntax#}</pre></td>
</ul>
</td>
<td>
<pre>{#syntax#}u8(200) *% 2 == 144{#endsyntax#}</pre>
<pre>{#syntax#}@as(u8, 200) *% 2 == 144{#endsyntax#}</pre>
</td>
</tr>
<tr>
@@ -1304,7 +1319,7 @@ a ^= b{#endsyntax#}</pre></td>
Bitwise NOT.
</td>
<td>
<pre>{#syntax#}~u8(0b10101111) == 0b01010000{#endsyntax#}</pre>
<pre>{#syntax#}~@as(u8, 0b10101111) == 0b01010000{#endsyntax#}</pre>
</td>
</tr>
<tr>
@@ -1538,7 +1553,7 @@ value == null{#endsyntax#}</pre>
const array1 = [_]u32{1,2};
const array2 = [_]u32{3,4};
const together = array1 ++ array2;
mem.eql(u32, together, [_]u32{1,2,3,4}){#endsyntax#}</pre>
mem.eql(u32, together, &[_]u32{1,2,3,4}){#endsyntax#}</pre>
</td>
</tr>
<tr>
@@ -1640,12 +1655,11 @@ comptime {
assert(message.len == 5);
}
// a string literal is an array literal
// A string literal is a pointer to an array literal.
const same_message = "hello";
comptime {
assert(mem.eql(u8, message, same_message));
assert(@typeOf(message) == @typeOf(same_message));
assert(mem.eql(u8, &message, same_message));
}
test "iterate over an array" {
@@ -1653,7 +1667,7 @@ test "iterate over an array" {
for (message) |byte| {
sum += byte;
}
assert(sum == usize('h') + usize('e') + usize('l') * 2 + usize('o'));
assert(sum == 'h' + 'e' + 'l' * 2 + 'o');
}
// modifiable array
@@ -1673,7 +1687,7 @@ const part_one = [_]i32{ 1, 2, 3, 4 };
const part_two = [_]i32{ 5, 6, 7, 8 };
const all_of_it = part_one ++ part_two;
comptime {
assert(mem.eql(i32, all_of_it, [_]i32{ 1, 2, 3, 4, 5, 6, 7, 8 }));
assert(mem.eql(i32, &all_of_it, &[_]i32{ 1, 2, 3, 4, 5, 6, 7, 8 }));
}
// remember that string literals are arrays
@@ -1735,6 +1749,43 @@ test "array initialization with function calls" {
{#code_end#}
{#see_also|for|Slices#}
{#header_open|Anonymous List Literals#}
<p>Similar to {#link|Enum Literals#} and {#link|Anonymous Struct Literals#}
the type can be omitted from array literals:</p>
{#code_begin|test|anon_list#}
const std = @import("std");
const assert = std.debug.assert;
test "anonymous list literal syntax" {
var array: [4]u8 = .{11, 22, 33, 44};
assert(array[0] == 11);
assert(array[1] == 22);
assert(array[2] == 33);
assert(array[3] == 44);
}
{#code_end#}
<p>
If there is no type in the result location then an anonymous list literal actually
turns into a {#link|struct#} with numbered field names:
</p>
{#code_begin|test|infer_list_literal#}
const std = @import("std");
const assert = std.debug.assert;
test "fully anonymous list literal" {
dump(.{ @as(u32, 1234), @as(f64, 12.34), true, "hi"});
}
fn dump(args: var) void {
assert(args.@"0" == 1234);
assert(args.@"1" == 12.34);
assert(args.@"2");
assert(args.@"3"[0] == 'h');
assert(args.@"3"[1] == 'i');
}
{#code_end#}
{#header_close#}
{#header_open|Multidimensional Arrays#}
<p>
Mutlidimensional arrays can be created by nesting arrays:
@@ -1764,6 +1815,26 @@ test "multidimensional arrays" {
}
{#code_end#}
{#header_close#}
{#header_open|Sentinel-Terminated Arrays#}
<p>
The syntax {#syntax#}[N:x]T{#endsyntax#} describes an array which has a sentinel element of value {#syntax#}x{#endsyntax#} at the
index corresponding to {#syntax#}len{#endsyntax#}.
</p>
{#code_begin|test|null_terminated_array#}
const std = @import("std");
const assert = std.debug.assert;
test "null terminated array" {
const array = [_:0]u8 {1, 2, 3, 4};
assert(@TypeOf(array) == [4:0]u8);
assert(array.len == 4);
assert(array[4] == 0);
}
{#code_end#}
{#see_also|Sentinel-Terminated Pointers|Sentinel-Terminated Slices#}
{#header_close#}
{#header_close#}
{#header_open|Vectors#}
@@ -1840,12 +1911,12 @@ test "address of syntax" {
assert(x_ptr.* == 1234);
// When you get the address of a const variable, you get a const pointer to a single item.
assert(@typeOf(x_ptr) == *const i32);
assert(@TypeOf(x_ptr) == *const i32);
// If you want to mutate the value, you'd need an address of a mutable variable:
var y: i32 = 5678;
const y_ptr = &y;
assert(@typeOf(y_ptr) == *i32);
assert(@TypeOf(y_ptr) == *i32);
y_ptr.* += 1;
assert(y_ptr.* == 5679);
}
@@ -1856,7 +1927,7 @@ test "pointer array access" {
// does not support pointer arithmetic.
var array = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
const ptr = &array[2];
assert(@typeOf(ptr) == *u8);
assert(@TypeOf(ptr) == *u8);
assert(array[2] == 3);
ptr.* += 1;
@@ -1864,7 +1935,7 @@ test "pointer array access" {
}
{#code_end#}
<p>
In Zig, we prefer slices over pointers to null-terminated arrays.
In Zig, we generally prefer {#link|Slices#} rather than {#link|Sentinel-Terminated Pointers#}.
You can turn an array or pointer into a slice using slice syntax.
</p>
<p>
@@ -1906,10 +1977,10 @@ test "comptime pointers" {
const assert = @import("std").debug.assert;
test "@ptrToInt and @intToPtr" {
const ptr = @intToPtr(*i32, 0xdeadbeef);
const ptr = @intToPtr(*i32, 0xdeadbee0);
const addr = @ptrToInt(ptr);
assert(@typeOf(addr) == usize);
assert(addr == 0xdeadbeef);
assert(@TypeOf(addr) == usize);
assert(addr == 0xdeadbee0);
}
{#code_end#}
<p>Zig is able to preserve memory addresses in comptime code, as long as
@@ -1921,10 +1992,10 @@ test "comptime @intToPtr" {
comptime {
// Zig is able to do this at compile-time, as long as
// ptr is never dereferenced.
const ptr = @intToPtr(*i32, 0xdeadbeef);
const ptr = @intToPtr(*i32, 0xdeadbee0);
const addr = @ptrToInt(ptr);
assert(@typeOf(addr) == usize);
assert(addr == 0xdeadbeef);
assert(@TypeOf(addr) == usize);
assert(addr == 0xdeadbee0);
}
}
{#code_end#}
@@ -1939,7 +2010,7 @@ const assert = @import("std").debug.assert;
test "volatile" {
const mmio_ptr = @intToPtr(*volatile u8, 0x12345678);
assert(@typeOf(mmio_ptr) == *volatile u8);
assert(@TypeOf(mmio_ptr) == *volatile u8);
}
{#code_end#}
<p>
@@ -1996,15 +2067,15 @@ const builtin = @import("builtin");
test "variable alignment" {
var x: i32 = 1234;
const align_of_i32 = @alignOf(@typeOf(x));
assert(@typeOf(&x) == *i32);
const align_of_i32 = @alignOf(@TypeOf(x));
assert(@TypeOf(&x) == *i32);
assert(*i32 == *align(align_of_i32) i32);
if (builtin.arch == builtin.Arch.x86_64) {
assert((*i32).alignment == 4);
}
}
{#code_end#}
<p>In the same way that a {#syntax#}*i32{#endsyntax#} can be {#link|implicitly cast|Implicit Casts#} to a
<p>In the same way that a {#syntax#}*i32{#endsyntax#} can be {#link|coerced|Type Coercion#} to a
{#syntax#}*const i32{#endsyntax#}, a pointer with a larger alignment can be implicitly
cast to a pointer with a smaller alignment, but not vice versa.
</p>
@@ -2018,10 +2089,10 @@ const assert = @import("std").debug.assert;
var foo: u8 align(4) = 100;
test "global variable alignment" {
assert(@typeOf(&foo).alignment == 4);
assert(@typeOf(&foo) == *align(4) u8);
const slice = (*[1]u8)(&foo)[0..];
assert(@typeOf(slice) == []align(4) u8);
assert(@TypeOf(&foo).alignment == 4);
assert(@TypeOf(&foo) == *align(4) u8);
const slice = @as(*[1]u8, &foo)[0..];
assert(@TypeOf(slice) == []align(4) u8);
}
fn derp() align(@sizeOf(usize) * 2) i32 { return 1234; }
@@ -2030,8 +2101,8 @@ fn noop4() align(4) void {}
test "function alignment" {
assert(derp() == 1234);
assert(@typeOf(noop1) == fn() align(1) void);
assert(@typeOf(noop4) == fn() align(4) void);
assert(@TypeOf(noop1) == fn() align(1) void);
assert(@TypeOf(noop4) == fn() align(4) void);
noop1();
noop4();
}
@@ -2062,8 +2133,10 @@ fn foo(bytes: []u8) u32 {
<p>
This pointer attribute allows a pointer to have address zero. This is only ever needed on the
freestanding OS target, where the address zero is mappable. If you want to represent null pointers, use
{#link|Optional Pointers#} instead. In this code example, if the pointer did not have the
{#syntax#}allowzero{#endsyntax#} attribute, this would be a {#link|Pointer Cast Invalid Null#} panic:
{#link|Optional Pointers#} instead. {#link|Optional Pointers#} with {#syntax#}allowzero{#endsyntax#}
are not the same size as pointers. In this code example, if the pointer
did not have the {#syntax#}allowzero{#endsyntax#} attribute, this would be a
{#link|Pointer Cast Invalid Null#} panic:
</p>
{#code_begin|test|allowzero#}
const std = @import("std");
@@ -2076,6 +2149,30 @@ test "allowzero" {
}
{#code_end#}
{#header_close#}
{#header_open|Sentinel-Terminated Pointers#}
<p>
The syntax {#syntax#}[*:x]T{#endsyntax#} describes a pointer that
has a length determined by a sentinel value. This provides protection
against buffer overflow and overreads.
</p>
{#code_begin|exe_build_err#}
{#link_libc#}
const std = @import("std");
// This is also available as `std.c.printf`.
pub extern "c" fn printf(format: [*:0]const u8, ...) c_int;
pub fn main() anyerror!void {
_ = printf("Hello, world!\n"); // OK
const msg = "Hello, world!\n";
const non_null_terminated_msg: [msg.len]u8 = msg.*;
_ = printf(&non_null_terminated_msg);
}
{#code_end#}
{#see_also|Sentinel-Terminated Slices|Sentinel-Terminated Arrays#}
{#header_close#}
{#header_close#}
{#header_open|Slices#}
@@ -2094,8 +2191,8 @@ test "basic slices" {
// Using the address-of operator on a slice gives a pointer to a single
// item, while using the `ptr` field gives an unknown length pointer.
assert(@typeOf(slice.ptr) == [*]i32);
assert(@typeOf(&slice[0]) == *i32);
assert(@TypeOf(slice.ptr) == [*]i32);
assert(@TypeOf(&slice[0]) == *i32);
assert(@ptrToInt(slice.ptr) == @ptrToInt(&slice[0]));
// Slices have array bounds checking. If you try to access something out
@@ -2115,7 +2212,7 @@ const fmt = @import("std").fmt;
test "using slices for strings" {
// Zig has no concept of strings. String literals are arrays of u8, and
// in general the string type is []u8 (slice of u8).
// Here we implicitly cast [5]u8 to []const u8
// Here we coerce [5]u8 to []const u8
const hello: []const u8 = "hello";
const world: []const u8 = "世界";
@@ -2123,7 +2220,7 @@ test "using slices for strings" {
// You can use slice syntax on an array to convert an array into a slice.
const all_together_slice = all_together[0..];
// String concatenation example.
const hello_world = try fmt.bufPrint(all_together_slice, "{} {}", hello, world);
const hello_world = try fmt.bufPrint(all_together_slice, "{} {}", .{hello, world});
// Generally, you can use UTF-8 and not worry about whether something is a
// string. If you don't need to deal with individual characters, no need
@@ -2140,7 +2237,7 @@ test "slice pointer" {
slice[2] = 3;
assert(slice[2] == 3);
// The slice is mutable because we sliced a mutable pointer.
assert(@typeOf(slice) == []u8);
assert(@TypeOf(slice) == []u8);
// You can also slice a slice:
const slice2 = slice[2..3];
@@ -2159,7 +2256,29 @@ test "slice widening" {
}
{#code_end#}
{#see_also|Pointers|for|Arrays#}
{#header_open|Sentinel-Terminated Slices#}
<p>
The syntax {#syntax#}[:x]T{#endsyntax#} is a slice which has a runtime known length
and also guarantees a sentinel value at the element indexed by the length. The type does not
guarantee that there are no sentinel elements before that. Sentinel-terminated slices allow element
access to the {#syntax#}len{#endsyntax#} index.
</p>
{#code_begin|test|null_terminated_slice#}
const std = @import("std");
const assert = std.debug.assert;
test "null terminated slice" {
const slice: [:0]const u8 = "hello";
assert(slice.len == 5);
assert(slice[5] == 0);
}
{#code_end#}
{#see_also|Sentinel-Terminated Pointers|Sentinel-Terminated Arrays#}
{#header_close#}
{#header_close#}
{#header_open|struct#}
{#code_begin|test|structs#}
// Declare a struct.
@@ -2527,7 +2646,8 @@ test "overaligned pointer to packed struct" {
Don't worry, there will be a good solution for this use case in zig.
</p>
{#header_close#}
{#header_open|struct Naming#}
{#header_open|Struct Naming#}
<p>Since all structs are anonymous, Zig infers the type name based on a few rules.</p>
<ul>
<li>If the struct is in the initialization expression of a variable, it gets named after
@@ -2541,9 +2661,9 @@ const std = @import("std");
pub fn main() void {
const Foo = struct {};
std.debug.warn("variable: {}\n", @typeName(Foo));
std.debug.warn("anonymous: {}\n", @typeName(struct {}));
std.debug.warn("function: {}\n", @typeName(List(i32)));
std.debug.warn("variable: {}\n", .{@typeName(Foo)});
std.debug.warn("anonymous: {}\n", .{@typeName(struct {})});
std.debug.warn("function: {}\n", .{@typeName(List(i32))});
}
fn List(comptime T: type) type {
@@ -2553,6 +2673,53 @@ fn List(comptime T: type) type {
}
{#code_end#}
{#header_close#}
{#header_open|Anonymous Struct Literals#}
<p>
Zig allows omitting the struct type of a literal. When the result is {#link|coerced|Type Coercion#},
the struct literal will directly instantiate the result location, with no copy:
</p>
{#code_begin|test|struct_result#}
const std = @import("std");
const assert = std.debug.assert;
const Point = struct {x: i32, y: i32};
test "anonymous struct literal" {
var pt: Point = .{
.x = 13,
.y = 67,
};
assert(pt.x == 13);
assert(pt.y == 67);
}
{#code_end#}
<p>
The struct type can be inferred. Here the result location does not include a type, and
so Zig infers the type:
</p>
{#code_begin|test|struct_anon#}
const std = @import("std");
const assert = std.debug.assert;
test "fully anonymous struct" {
dump(.{
.int = @as(u32, 1234),
.float = @as(f64, 12.34),
.b = true,
.s = "hi",
});
}
fn dump(args: var) void {
assert(args.int == 1234);
assert(args.float == 12.34);
assert(args.b);
assert(args.s[0] == 'h');
assert(args.s[1] == 'i');
}
{#code_end#}
{#header_close#}
{#see_also|comptime|@fieldParentPtr#}
{#header_close#}
{#header_open|enum#}
@@ -2663,7 +2830,7 @@ test "@tagName" {
<p>
By default, enums are not guaranteed to be compatible with the C ABI:
</p>
{#code_begin|obj_err|parameter of type 'Foo' not allowed in function with calling convention 'ccc'#}
{#code_begin|obj_err|parameter of type 'Foo' not allowed in function with calling convention 'C'#}
const Foo = enum { A, B, C };
export fn entry(foo: Foo) void { }
{#code_end#}
@@ -2779,6 +2946,7 @@ test "simple union" {
This turns the union into a <em>tagged</em> union, which makes it eligible
to use with {#link|switch#} expressions. One can use {#link|@TagType#} to
obtain the enum type from the union type.
Tagged unions coerce to their enum {#link|Type Coercion: unions and enums#}
</p>
{#code_begin|test#}
const std = @import("std");
@@ -2795,7 +2963,7 @@ const ComplexType = union(ComplexTypeTag) {
test "switch on tagged union" {
const c = ComplexType{ .Ok = 42 };
assert(ComplexTypeTag(c) == ComplexTypeTag.Ok);
assert(@as(ComplexTypeTag, c) == ComplexTypeTag.Ok);
switch (c) {
ComplexTypeTag.Ok => |value| assert(value == 42),
@@ -2806,6 +2974,14 @@ test "switch on tagged union" {
test "@TagType" {
assert(@TagType(ComplexType) == ComplexTypeTag);
}
test "coerce to enum" {
const c1 = ComplexType{ .Ok = 42 };
const c2 = ComplexType.NotOk;
assert(c1 == .Ok);
assert(c2 == .NotOk);
}
{#code_end#}
<p>In order to modify the payload of a tagged union in a switch expression,
place a {#syntax#}*{#endsyntax#} before the variable name to make it a pointer:
@@ -2825,7 +3001,7 @@ const ComplexType = union(ComplexTypeTag) {
test "modify tagged union in switch" {
var c = ComplexType{ .Ok = 42 };
assert(ComplexTypeTag(c) == ComplexTypeTag.Ok);
assert(@as(ComplexTypeTag, c) == ComplexTypeTag.Ok);
switch (c) {
ComplexTypeTag.Ok => |*value| value.* += 1,
@@ -2898,6 +3074,32 @@ test "@tagName" {
<p>A {#syntax#}packed union{#endsyntax#} has well-defined in-memory layout and is eligible
to be in a {#link|packed struct#}.
{#header_close#}
{#header_open|Anonymous Union Literals#}
<p>{#link|Anonymous Struct Literals#} syntax can be used to initialize unions without specifying
the type:</p>
{#code_begin|test|anon_union#}
const std = @import("std");
const assert = std.debug.assert;
const Number = union {
int: i32,
float: f64,
};
test "anonymous union literal syntax" {
var i: Number = .{.int = 42};
var f = makeNumber();
assert(i.int == 42);
assert(f.float == 12.34);
}
fn makeNumber() Number {
return .{.float = 12.34};
}
{#code_end#}
{#header_close#}
{#header_close#}
{#header_open|blocks#}
@@ -3393,7 +3595,7 @@ test "for basics" {
// This is zero-indexed.
var sum2: i32 = 0;
for (items) |value, i| {
assert(@typeOf(i) == usize);
assert(@TypeOf(i) == usize);
sum2 += @intCast(i32, i);
}
assert(sum2 == 10);
@@ -3513,6 +3715,14 @@ fn typeNameLength(comptime T: type) usize {
const assert = @import("std").debug.assert;
test "if expression" {
// If expressions are used instead of a ternary expression.
const a: u32 = 5;
const b: u32 = 4;
const result = if (a != b) 47 else 3089;
assert(result == 47);
}
test "if boolean" {
// If expressions test boolean conditions.
const a: u32 = 5;
@@ -3524,10 +3734,6 @@ test "if boolean" {
} else {
unreachable;
}
// If expressions are used instead of a ternary expression.
const result = if (a != b) 47 else 3089;
assert(result == 47);
}
test "if optional" {
@@ -3642,18 +3848,18 @@ test "defer basics" {
// If multiple defer statements are specified, they will be executed in
// the reverse order they were run.
fn deferUnwindExample() void {
warn("\n");
warn("\n", .{});
defer {
warn("1 ");
warn("1 ", .{});
}
defer {
warn("2 ");
warn("2 ", .{});
}
if (false) {
// defers are not run if they are never executed.
defer {
warn("3 ");
warn("3 ", .{});
}
}
}
@@ -3668,15 +3874,15 @@ test "defer unwinding" {
// This is especially useful in allowing a function to clean up properly
// on error, and replaces goto error handling tactics as seen in c.
fn deferErrorExample(is_error: bool) !void {
warn("\nstart of function\n");
warn("\nstart of function\n", .{});
// This will always be executed on exit
defer {
warn("end of function\n");
warn("end of function\n", .{});
}
errdefer {
warn("encountered an error!\n");
warn("encountered an error!\n", .{});
}
if (is_error) {
@@ -3736,7 +3942,7 @@ test "type of unreachable" {
// However this assertion will still fail because
// evaluating unreachable at compile-time is a compile error.
assert(@typeOf(unreachable) == noreturn);
assert(@TypeOf(unreachable) == noreturn);
}
}
{#code_end#}
@@ -3769,7 +3975,7 @@ test "noreturn" {
<p>Another use case for {#syntax#}noreturn{#endsyntax#} is the {#syntax#}exit{#endsyntax#} function:</p>
{#code_begin|test#}
{#target_windows#}
pub extern "kernel32" stdcallcc fn ExitProcess(exit_code: c_uint) noreturn;
pub extern "kernel32" fn ExitProcess(exit_code: c_uint) callconv(.Stdcall) noreturn;
test "foo" {
const value = bar() catch ExitProcess(1);
@@ -3803,8 +4009,8 @@ export fn sub(a: i8, b: i8) i8 { return a - b; }
// The extern specifier is used to declare a function that will be resolved
// at link time, when linking statically, or at runtime, when linking
// dynamically.
// The stdcallcc specifier changes the calling convention of the function.
extern "kernel32" stdcallcc fn ExitProcess(exit_code: u32) noreturn;
// The callconv specifier changes the calling convention of the function.
extern "kernel32" fn ExitProcess(exit_code: u32) callconv(.Stdcall) noreturn;
extern "c" fn atan2(a: f64, b: f64) f64;
// The @setCold builtin tells the optimizer that a function is rarely called.
@@ -3813,9 +4019,9 @@ fn abort() noreturn {
while (true) {}
}
// The nakedcc specifier makes a function not have any function prologue or epilogue.
// The naked calling convention makes a function not have any function prologue or epilogue.
// This can be useful when integrating with assembly.
nakedcc fn _start() noreturn {
fn _start() callconv(.Naked) noreturn {
abort();
}
@@ -3845,7 +4051,7 @@ test "function" {
const assert = @import("std").debug.assert;
comptime {
assert(@typeOf(foo) == fn()void);
assert(@TypeOf(foo) == fn()void);
assert(@sizeOf(fn()void) == @sizeOf(?fn()void));
}
@@ -3887,14 +4093,37 @@ test "pass struct to function" {
<p>
For extern functions, Zig follows the C ABI for passing structs and unions by value.
</p>
{#header_close#}
{#header_open|Function Parameter Type Inference#}
<p>
Function parameters can be declared with {#syntax#}var{#endsyntax#} in place of the type.
In this case the parameter types will be inferred when the function is called.
Use {#link|@TypeOf#} and {#link|@typeInfo#} to get information about the inferred type.
</p>
{#code_begin|test#}
const assert = @import("std").debug.assert;
fn addFortyTwo(x: var) @TypeOf(x) {
return x + 42;
}
test "fn type inference" {
assert(addFortyTwo(1) == 43);
assert(@TypeOf(addFortyTwo(1)) == comptime_int);
var y: i64 = 2;
assert(addFortyTwo(y) == 44);
assert(@TypeOf(addFortyTwo(y)) == i64);
}
{#code_end#}
{#header_close#}
{#header_open|Function Reflection#}
{#code_begin|test#}
const assert = @import("std").debug.assert;
test "fn reflection" {
assert(@typeOf(assert).ReturnType == void);
assert(@typeOf(assert).is_var_args == false);
assert(@TypeOf(assert).ReturnType == void);
assert(@TypeOf(assert).is_var_args == false);
}
{#code_end#}
{#header_close#}
@@ -3912,7 +4141,7 @@ test "fn reflection" {
However right now it is hard coded to be a {#syntax#}u16{#endsyntax#}. See <a href="https://github.com/ziglang/zig/issues/786">#768</a>.
</p>
<p>
You can {#link|implicitly cast|Implicit Casts#} an error from a subset to a superset:
You can {#link|coerce|Type Coercion#} an error from a subset to a superset:
</p>
{#code_begin|test#}
const std = @import("std");
@@ -3927,7 +4156,7 @@ const AllocationError = error {
OutOfMemory,
};
test "implicit cast subset to superset" {
test "coerce subset to superset" {
const err = foo(AllocationError.OutOfMemory);
std.debug.assert(err == FileOpenError.OutOfMemory);
}
@@ -3937,7 +4166,7 @@ fn foo(err: AllocationError) FileOpenError {
}
{#code_end#}
<p>
But you cannot implicitly cast an error from a superset to a subset:
But you cannot {#link|coerce|Type Coercion#} an error from a superset to a subset:
</p>
{#code_begin|test_err|not a member of destination error set#}
const FileOpenError = error {
@@ -3950,7 +4179,7 @@ const AllocationError = error {
OutOfMemory,
};
test "implicit cast superset to subset" {
test "coerce superset to subset" {
foo(FileOpenError.OutOfMemory) catch {};
}
@@ -3977,7 +4206,7 @@ const err = (error {FileNotFound}).FileNotFound;
It is a superset of all other error sets and a subset of none of them.
</p>
<p>
You can implicitly cast any error set to the global one, and you can explicitly
You can {#link|coerce|Type Coercion#} any error set to the global one, and you can explicitly
cast an error of the global error set to a non-global one. This inserts a language-level
assert to make sure the error value is in fact in the destination error set.
</p>
@@ -4048,7 +4277,7 @@ test "parse u64" {
<p>
Within the function definition, you can see some return statements that return
an error, and at the bottom a return statement that returns a {#syntax#}u64{#endsyntax#}.
Both types {#link|implicitly cast|Implicit Casts#} to {#syntax#}anyerror!u64{#endsyntax#}.
Both types {#link|coerce|Type Coercion#} to {#syntax#}anyerror!u64{#endsyntax#}.
</p>
<p>
What it looks like to use this function varies depending on what you're
@@ -4187,17 +4416,17 @@ const assert = @import("std").debug.assert;
test "error union" {
var foo: anyerror!i32 = undefined;
// Implicitly cast from child type of an error union:
// Coerce from child type of an error union:
foo = 1234;
// Implicitly cast from an error set:
// Coerce from an error set:
foo = error.SomeError;
// Use compile-time reflection to access the payload type of an error union:
comptime assert(@typeOf(foo).Payload == i32);
comptime assert(@TypeOf(foo).Payload == i32);
// Use compile-time reflection to access the error set type of an error union:
comptime assert(@typeOf(foo).ErrorSet == anyerror);
comptime assert(@TypeOf(foo).ErrorSet == anyerror);
}
{#code_end#}
{#header_open|Merging Error Sets#}
@@ -4567,14 +4796,14 @@ fn doAThing(optional_foo: ?*Foo) void {
const assert = @import("std").debug.assert;
test "optional type" {
// Declare an optional and implicitly cast from null:
// Declare an optional and coerce from null:
var foo: ?i32 = null;
// Implicitly cast from child type of an optional
// Coerce from child type of an optional
foo = 1234;
// Use compile-time reflection to access the child type of the optional:
comptime assert(@typeOf(foo).Child == i32);
comptime assert(@TypeOf(foo).Child == i32);
}
{#code_end#}
{#header_close#}
@@ -4613,38 +4842,38 @@ test "optional pointers" {
{#header_open|Casting#}
<p>
A <strong>type cast</strong> converts a value of one type to another.
Zig has {#link|Implicit Casts#} for conversions that are known to be completely safe and unambiguous,
Zig has {#link|Type Coercion#} for conversions that are known to be completely safe and unambiguous,
and {#link|Explicit Casts#} for conversions that one would not want to happen on accident.
There is also a third kind of type conversion called {#link|Peer Type Resolution#} for
the case when a result type must be decided given multiple operand types.
</p>
{#header_open|Implicit Casts#}
{#header_open|Type Coercion#}
<p>
An implicit cast occurs when one type is expected, but different type is provided:
Type coercion occurs when one type is expected, but different type is provided:
</p>
{#code_begin|test#}
test "implicit cast - variable declaration" {
test "type coercion - variable declaration" {
var a: u8 = 1;
var b: u16 = a;
}
test "implicit cast - function call" {
test "type coercion - function call" {
var a: u8 = 1;
foo(a);
}
fn foo(b: u16) void {}
test "implicit cast - invoke a type as a function" {
test "type coercion - @as builtin" {
var a: u8 = 1;
var b = u16(a);
var b = @as(u16, a);
}
{#code_end#}
<p>
Implicit casts are only allowed when it is completely unambiguous how to get from one type to another,
Type coercions are only allowed when it is completely unambiguous how to get from one type to another,
and the transformation is guaranteed to be safe. There is one exception, which is {#link|C Pointers#}.
</p>
{#header_open|Implicit Cast: Stricter Qualification#}
{#header_open|Type Coercion: Stricter Qualification#}
<p>
Values which have the same representation at runtime can be cast to increase the strictness
of the qualifiers, no matter how nested the qualifiers are:
@@ -4659,7 +4888,7 @@ test "implicit cast - invoke a type as a function" {
These casts are no-ops at runtime since the value representation does not change.
</p>
{#code_begin|test#}
test "implicit cast - const qualification" {
test "type coercion - const qualification" {
var a: i32 = 1;
var b: *i32 = &a;
foo(b);
@@ -4668,7 +4897,7 @@ test "implicit cast - const qualification" {
fn foo(a: *const i32) void {}
{#code_end#}
<p>
In addition, pointers implicitly cast to const optional pointers:
In addition, pointers coerce to const optional pointers:
</p>
{#code_begin|test#}
const std = @import("std");
@@ -4676,16 +4905,16 @@ const assert = std.debug.assert;
const mem = std.mem;
test "cast *[1][*]const u8 to [*]const ?[*]const u8" {
const window_name = [1][*]const u8{c"window name"};
const window_name = [1][*]const u8{"window name"};
const x: [*]const ?[*]const u8 = &window_name;
assert(mem.eql(u8, std.mem.toSliceConst(u8, x[0].?), "window name"));
assert(mem.eql(u8, std.mem.toSliceConst(u8, @ptrCast([*:0]const u8, x[0].?)), "window name"));
}
{#code_end#}
{#header_close#}
{#header_open|Implicit Cast: Integer and Float Widening#}
{#header_open|Type Coercion: Integer and Float Widening#}
<p>
{#link|Integers#} implicitly cast to integer types which can represent every value of the old type, and likewise
{#link|Floats#} implicitly cast to float types which can represent every value of the old type.
{#link|Integers#} coerce to integer types which can represent every value of the old type, and likewise
{#link|Floats#} coerce to float types which can represent every value of the old type.
</p>
{#code_begin|test#}
const std = @import("std");
@@ -4717,8 +4946,8 @@ test "float widening" {
}
{#code_end#}
{#header_close#}
{#header_open|Implicit Cast: Arrays and Pointers#}
{#code_begin|test#}
{#header_open|Type Coercion: Arrays and Pointers#}
{#code_begin|test|coerce_arrays_and_ptrs#}
const std = @import("std");
const assert = std.debug.assert;
@@ -4728,48 +4957,48 @@ const assert = std.debug.assert;
// https://github.com/ziglang/zig/issues/265 is implemented.
test "[N]T to []const T" {
var x1: []const u8 = "hello";
var x2: []const u8 = [5]u8{ 'h', 'e', 'l', 'l', 111 };
var x2: []const u8 = &[5]u8{ 'h', 'e', 'l', 'l', 111 };
assert(std.mem.eql(u8, x1, x2));
var y: []const f32 = [2]f32{ 1.2, 3.4 };
var y: []const f32 = &[2]f32{ 1.2, 3.4 };
assert(y[0] == 1.2);
}
// Likewise, it works when the destination type is an error union.
test "[N]T to E![]const T" {
var x1: anyerror![]const u8 = "hello";
var x2: anyerror![]const u8 = [5]u8{ 'h', 'e', 'l', 'l', 111 };
var x2: anyerror![]const u8 = &[5]u8{ 'h', 'e', 'l', 'l', 111 };
assert(std.mem.eql(u8, try x1, try x2));
var y: anyerror![]const f32 = [2]f32{ 1.2, 3.4 };
var y: anyerror![]const f32 = &[2]f32{ 1.2, 3.4 };
assert((try y)[0] == 1.2);
}
// Likewise, it works when the destination type is an optional.
test "[N]T to ?[]const T" {
var x1: ?[]const u8 = "hello";
var x2: ?[]const u8 = [5]u8{ 'h', 'e', 'l', 'l', 111 };
var x2: ?[]const u8 = &[5]u8{ 'h', 'e', 'l', 'l', 111 };
assert(std.mem.eql(u8, x1.?, x2.?));
var y: ?[]const f32 = [2]f32{ 1.2, 3.4 };
var y: ?[]const f32 = &[2]f32{ 1.2, 3.4 };
assert(y.?[0] == 1.2);
}
// In this cast, the array length becomes the slice length.
test "*[N]T to []T" {
var buf: [5]u8 = "hello";
var buf: [5]u8 = "hello".*;
const x: []u8 = &buf;
assert(std.mem.eql(u8, x, "hello"));
const buf2 = [2]f32{ 1.2, 3.4 };
const x2: []const f32 = &buf2;
assert(std.mem.eql(f32, x2, [2]f32{ 1.2, 3.4 }));
assert(std.mem.eql(f32, x2, &[2]f32{ 1.2, 3.4 }));
}
// Single-item pointers to arrays can be implicitly casted to
// Single-item pointers to arrays can be coerced to
// unknown length pointers.
test "*[N]T to [*]T" {
var buf: [5]u8 = "hello";
var buf: [5]u8 = "hello".*;
const x: [*]u8 = &buf;
assert(x[4] == 'o');
// x[5] would be an uncaught out of bounds pointer dereference!
@@ -4777,7 +5006,7 @@ test "*[N]T to [*]T" {
// Likewise, it works when the destination type is an optional.
test "*[N]T to ?[*]T" {
var buf: [5]u8 = "hello";
var buf: [5]u8 = "hello".*;
const x: ?[*]u8 = &buf;
assert(x.?[4] == 'o');
}
@@ -4792,15 +5021,15 @@ test "*T to *[1]T" {
{#code_end#}
{#see_also|C Pointers#}
{#header_close#}
{#header_open|Implicit Cast: Optionals#}
{#header_open|Type Coercion: Optionals#}
<p>
The payload type of {#link|Optionals#}, as well as {#link|null#}, implicitly cast to the optional type.
The payload type of {#link|Optionals#}, as well as {#link|null#}, coerce to the optional type.
</p>
{#code_begin|test#}
const std = @import("std");
const assert = std.debug.assert;
test "implicit casting to optionals" {
test "coerce to optionals" {
const x: ?i32 = 1234;
const y: ?i32 = null;
@@ -4813,7 +5042,7 @@ test "implicit casting to optionals" {
const std = @import("std");
const assert = std.debug.assert;
test "implicit casting to optionals wrapped in error union" {
test "coerce to optionals wrapped in error union" {
const x: anyerror!?i32 = 1234;
const y: anyerror!?i32 = null;
@@ -4822,15 +5051,15 @@ test "implicit casting to optionals wrapped in error union" {
}
{#code_end#}
{#header_close#}
{#header_open|Implicit Cast: Error Unions#}
{#header_open|Type Coercion: Error Unions#}
<p>The payload type of an {#link|Error Union Type#} as well as the {#link|Error Set Type#}
implicitly cast to the error union type:
coerce to the error union type:
</p>
{#code_begin|test#}
const std = @import("std");
const assert = std.debug.assert;
test "implicit casting to error unions" {
test "coercion to error unions" {
const x: anyerror!i32 = 1234;
const y: anyerror!i32 = error.Failure;
@@ -4839,23 +5068,23 @@ test "implicit casting to error unions" {
}
{#code_end#}
{#header_close#}
{#header_open|Implicit Cast: Compile-Time Known Numbers#}
{#header_open|Type Coercion: Compile-Time Known Numbers#}
<p>When a number is {#link|comptime#}-known to be representable in the destination type,
it may be implicitly casted:
it may be coerced:
</p>
{#code_begin|test#}
const std = @import("std");
const assert = std.debug.assert;
test "implicit casting large integer type to smaller one when value is comptime known to fit" {
test "coercing large integer type to smaller one when value is comptime known to fit" {
const x: u64 = 255;
const y: u8 = x;
assert(y == 255);
}
{#code_end#}
{#header_close#}
{#header_open|Implicit Cast: unions and enums#}
<p>Tagged unions can be implicitly cast to enums, and enums can be implicitly casted to tagged unions
{#header_open|Type Coercion: unions and enums#}
<p>Tagged unions can be coerced to enums, and enums can be coerced to tagged unions
when they are {#link|comptime#}-known to be a field of the union that has only one possible value, such as
{#link|void#}:
</p>
@@ -4875,7 +5104,7 @@ const U = union(E) {
Three,
};
test "implicit casting between unions and enums" {
test "coercion between unions and enums" {
var u = U{ .Two = 12.34 };
var e: E = u;
assert(e == E.Two);
@@ -4887,20 +5116,20 @@ test "implicit casting between unions and enums" {
{#code_end#}
{#see_also|union|enum#}
{#header_close#}
{#header_open|Implicit Cast: Zero Bit Types#}
<p>{#link|Zero Bit Types#} may be implicitly casted to single-item {#link|Pointers#},
{#header_open|Type Coercion: Zero Bit Types#}
<p>{#link|Zero Bit Types#} may be coerced to single-item {#link|Pointers#},
regardless of const.</p>
<p>TODO document the reasoning for this</p>
<p>TODO document whether vice versa should work and why</p>
{#code_begin|test#}
test "implicit casting of zero bit types" {
test "coercion of zero bit types" {
var x: void = {};
var y: *void = x;
//var z: void = y; // TODO
}
{#code_end#}
{#header_close#}
{#header_open|Implicit Cast: undefined#}
{#header_open|Type Coercion: undefined#}
<p>{#link|undefined#} can be cast to any type.</p>
{#header_close#}
{#header_close#}
@@ -4945,10 +5174,10 @@ test "implicit casting of zero bit types" {
<li>Some {#link|binary operations|Table of Operators#}</li>
</ul>
<p>
This kind of type resolution chooses a type that all peer types can implicitly cast into. Here are
This kind of type resolution chooses a type that all peer types can coerce into. Here are
some examples:
</p>
{#code_begin|test#}
{#code_begin|test|peer_type_resolution#}
const std = @import("std");
const assert = std.debug.assert;
const mem = std.mem;
@@ -4958,7 +5187,7 @@ test "peer resolve int widening" {
var b: i16 = 34;
var c = a + b;
assert(c == 46);
assert(@typeOf(c) == i16);
assert(@TypeOf(c) == i16);
}
test "peer resolve arrays of different size to const slice" {
@@ -4976,8 +5205,8 @@ test "peer resolve array and const slice" {
comptime testPeerResolveArrayConstSlice(true);
}
fn testPeerResolveArrayConstSlice(b: bool) void {
const value1 = if (b) "aoeu" else ([]const u8)("zz");
const value2 = if (b) ([]const u8)("zz") else "aoeu";
const value1 = if (b) "aoeu" else @as([]const u8, "zz");
const value2 = if (b) @as([]const u8, "zz") else "aoeu";
assert(mem.eql(u8, value1, "aoeu"));
assert(mem.eql(u8, value2, "zz"));
}
@@ -4992,13 +5221,13 @@ test "peer type resolution: ?T and T" {
}
fn peerTypeTAndOptionalT(c: bool, b: bool) ?usize {
if (c) {
return if (b) null else usize(0);
return if (b) null else @as(usize, 0);
}
return usize(3);
return @as(usize, 3);
}
test "peer type resolution: [0]u8 and []const u8" {
test "peer type resolution: *[0]u8 and []const u8" {
assert(peerTypeEmptyArrayAndSlice(true, "hi").len == 0);
assert(peerTypeEmptyArrayAndSlice(false, "hi").len == 1);
comptime {
@@ -5008,20 +5237,20 @@ test "peer type resolution: [0]u8 and []const u8" {
}
fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) []const u8 {
if (a) {
return [_]u8{};
return &[_]u8{};
}
return slice[0..1];
}
test "peer type resolution: [0]u8, []const u8, and anyerror![]u8" {
test "peer type resolution: *[0]u8, []const u8, and anyerror![]u8" {
{
var data = "hi";
var data = "hi".*;
const slice = data[0..];
assert((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
assert((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
}
comptime {
var data = "hi";
var data = "hi".*;
const slice = data[0..];
assert((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
assert((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
@@ -5029,15 +5258,15 @@ test "peer type resolution: [0]u8, []const u8, and anyerror![]u8" {
}
fn peerTypeEmptyArrayAndSliceAndError(a: bool, slice: []u8) anyerror![]u8 {
if (a) {
return [_]u8{};
return &[_]u8{};
}
return slice[0..1];
}
test "peer type resolution: *const T and ?*T" {
const a = @intToPtr(*const usize, 0x123456789);
const b = @intToPtr(?*usize, 0x123456789);
const a = @intToPtr(*const usize, 0x123456780);
const b = @intToPtr(?*usize, 0x123456780);
assert(a == b);
assert(b == a);
}
@@ -5258,11 +5487,9 @@ fn gimmeTheBiggerInteger(a: u64, b: u64) u64 {
<li>In the function definition, the value is known at compile-time.</li>
</ul>
<p>
</p>
<p>
For example, if we were to introduce another function to the above snippet:
</p>
{#code_begin|test_err|cannot store runtime value in type 'type'#}
{#code_begin|test_err|values of type 'type' must be comptime known#}
fn max(comptime T: type, a: T, b: T) T {
return if (a > b) a else b;
}
@@ -5559,7 +5786,7 @@ test "fibonacci" {
</p>
{#code_begin|test#}
const first_25_primes = firstNPrimes(25);
const sum_of_first_25_primes = sum(first_25_primes);
const sum_of_first_25_primes = sum(&first_25_primes);
fn firstNPrimes(comptime n: usize) [n]i32 {
var prime_list: [n]i32 = undefined;
@@ -5658,7 +5885,7 @@ const a_number: i32 = 1234;
const a_string = "foobar";
pub fn main() void {
warn("here is a string: '{}' here is a number: {}\n", a_string, a_number);
warn("here is a string: '{}' here is a number: {}\n", .{a_string, a_number});
}
{#code_end#}
@@ -5668,7 +5895,7 @@ pub fn main() void {
{#code_begin|syntax#}
/// Calls print and then flushes the buffer.
pub fn printf(self: *OutStream, comptime format: []const u8, args: ...) anyerror!void {
pub fn printf(self: *OutStream, comptime format: []const u8, args: var) anyerror!void {
const State = enum {
Start,
OpenBrace,
@@ -5755,7 +5982,7 @@ pub fn printf(self: *OutStream, arg0: i32, arg1: []const u8) !void {
</p>
{#code_begin|syntax#}
pub fn printValue(self: *OutStream, value: var) !void {
const T = @typeOf(value);
const T = @TypeOf(value);
if (@isInteger(T)) {
return self.printInt(T, value);
} else if (@isFloat(T)) {
@@ -5775,8 +6002,11 @@ const a_number: i32 = 1234;
const a_string = "foobar";
test "printf too many arguments" {
warn("here is a string: '{}' here is a number: {}\n",
a_string, a_number, a_number);
warn("here is a string: '{}' here is a number: {}\n", .{
a_string,
a_number,
a_number,
});
}
{#code_end#}
<p>
@@ -5784,7 +6014,7 @@ test "printf too many arguments" {
</p>
<p>
Zig doesn't care whether the format argument is a string literal,
only that it is a compile-time known value that is implicitly castable to a {#syntax#}[]const u8{#endsyntax#}:
only that it is a compile-time known value that can be coerced to a {#syntax#}[]const u8{#endsyntax#}:
</p>
{#code_begin|exe|printf#}
const warn = @import("std").debug.warn;
@@ -5794,7 +6024,7 @@ const a_string = "foobar";
const fmt = "here is a string: '{}' here is a number: {}\n";
pub fn main() void {
warn(fmt, a_string, a_number);
warn(fmt, .{a_string, a_number});
}
{#code_end#}
<p>
@@ -5819,7 +6049,7 @@ pub fn main() void {
{#target_linux_x86_64#}
pub fn main() noreturn {
const msg = "hello world\n";
_ = syscall3(SYS_write, STDOUT_FILENO, @ptrToInt(&msg), msg.len);
_ = syscall3(SYS_write, STDOUT_FILENO, @ptrToInt(msg), msg.len);
_ = syscall1(SYS_exit, 0);
unreachable;
}
@@ -6068,7 +6298,7 @@ test "async function suspend with block" {
fn testSuspendBlock() void {
suspend {
comptime assert(@typeOf(@frame()) == *@Frame(testSuspendBlock));
comptime assert(@TypeOf(@frame()) == *@Frame(testSuspendBlock));
the_frame = @frame();
}
result = true;
@@ -6135,7 +6365,7 @@ test "async and await" {
fn amain() void {
var frame = async func();
comptime assert(@typeOf(frame) == @Frame(func));
comptime assert(@TypeOf(frame) == @Frame(func));
const ptr: anyframe->void = &frame;
const any_ptr: anyframe = ptr;
@@ -6154,7 +6384,7 @@ fn func() void {
</p>
<p>
{#syntax#}await{#endsyntax#} is a suspend point, and takes as an operand anything that
implicitly casts to {#syntax#}anyframe->T{#endsyntax#}.
coerces to {#syntax#}anyframe->T{#endsyntax#}.
</p>
<p>
There is a common misconception that {#syntax#}await{#endsyntax#} resumes the target function.
@@ -6177,7 +6407,7 @@ test "async function await" {
resume the_frame;
seq('i');
assert(final_result == 1234);
assert(std.mem.eql(u8, seq_points, "abcdefghi"));
assert(std.mem.eql(u8, &seq_points, "abcdefghi"));
}
fn amain() void {
seq('b');
@@ -6232,7 +6462,7 @@ pub fn main() void {
fn amainWrap() void {
amain() catch |e| {
std.debug.warn("{}\n", e);
std.debug.warn("{}\n", .{e});
if (@errorReturnTrace()) |trace| {
std.debug.dumpStackTrace(trace.*);
}
@@ -6241,7 +6471,7 @@ fn amainWrap() void {
}
fn amain() !void {
const allocator = std.heap.direct_allocator;
const allocator = std.heap.page_allocator;
var download_frame = async fetchUrl(allocator, "https://example.com/");
var awaited_download_frame = false;
errdefer if (!awaited_download_frame) {
@@ -6262,8 +6492,8 @@ fn amain() !void {
const download_text = try await download_frame;
defer allocator.free(download_text);
std.debug.warn("download_text: {}\n", download_text);
std.debug.warn("file_text: {}\n", file_text);
std.debug.warn("download_text: {}\n", .{download_text});
std.debug.warn("file_text: {}\n", .{file_text});
}
var global_download_frame: anyframe = undefined;
@@ -6273,7 +6503,7 @@ fn fetchUrl(allocator: *Allocator, url: []const u8) ![]u8 {
suspend {
global_download_frame = @frame();
}
std.debug.warn("fetchUrl returning\n");
std.debug.warn("fetchUrl returning\n", .{});
return result;
}
@@ -6284,7 +6514,7 @@ fn readFile(allocator: *Allocator, filename: []const u8) ![]u8 {
suspend {
global_file_frame = @frame();
}
std.debug.warn("readFile returning\n");
std.debug.warn("readFile returning\n", .{});
return result;
}
{#code_end#}
@@ -6302,7 +6532,7 @@ pub fn main() void {
fn amainWrap() void {
amain() catch |e| {
std.debug.warn("{}\n", e);
std.debug.warn("{}\n", .{e});
if (@errorReturnTrace()) |trace| {
std.debug.dumpStackTrace(trace.*);
}
@@ -6311,7 +6541,7 @@ fn amainWrap() void {
}
fn amain() !void {
const allocator = std.heap.direct_allocator;
const allocator = std.heap.page_allocator;
var download_frame = async fetchUrl(allocator, "https://example.com/");
var awaited_download_frame = false;
errdefer if (!awaited_download_frame) {
@@ -6332,21 +6562,21 @@ fn amain() !void {
const download_text = try await download_frame;
defer allocator.free(download_text);
std.debug.warn("download_text: {}\n", download_text);
std.debug.warn("file_text: {}\n", file_text);
std.debug.warn("download_text: {}\n", .{download_text});
std.debug.warn("file_text: {}\n", .{file_text});
}
fn fetchUrl(allocator: *Allocator, url: []const u8) ![]u8 {
const result = try std.mem.dupe(allocator, u8, "this is the downloaded url contents");
errdefer allocator.free(result);
std.debug.warn("fetchUrl returning\n");
std.debug.warn("fetchUrl returning\n", .{});
return result;
}
fn readFile(allocator: *Allocator, filename: []const u8) ![]u8 {
const result = try std.mem.dupe(allocator, u8, "this is the file contents");
errdefer allocator.free(result);
std.debug.warn("readFile returning\n");
std.debug.warn("readFile returning\n", .{});
return result;
}
{#code_end#}
@@ -6359,7 +6589,7 @@ fn readFile(allocator: *Allocator, filename: []const u8) ![]u8 {
{#header_close#}
{#header_close#}
{#header_open|Builtin Functions|3col#}
{#header_open|Builtin Functions|2col#}
<p>
Builtin functions are provided by the compiler and are prefixed with <code>@</code>.
The {#syntax#}comptime{#endsyntax#} keyword on a parameter means that the parameter must be known
@@ -6414,6 +6644,14 @@ comptime {
</p>
{#header_close#}
{#header_open|@as#}
<pre>{#syntax#}@as(comptime T: type, expression) T{#endsyntax#}</pre>
<p>
Performs {#link|Type Coercion#}. This cast is allowed when the conversion is unambiguous and safe,
and is the preferred way to convert between types, whenever possible.
</p>
{#header_close#}
{#header_open|@asyncCall#}
<pre>{#syntax#}@asyncCall(frame_buffer: []align(@alignOf(@Frame(anyAsyncFunction))) u8, result_ptr, function_ptr, args: ...) anyframe->T{#endsyntax#}</pre>
<p>
@@ -6462,14 +6700,14 @@ async fn func(y: *i32) void {
This builtin function atomically dereferences a pointer and returns the value.
</p>
<p>
{#syntax#}T{#endsyntax#} must be a pointer type, a {#syntax#}bool{#endsyntax#},
or an integer whose bit count meets these requirements:
{#syntax#}T{#endsyntax#} must be a pointer type, a {#syntax#}bool{#endsyntax#}, a float,
an integer whose bit count meets these requirements:
</p>
<ul>
<li>At least 8</li>
<li>At most the same as usize</li>
<li>Power of 2</li>
</ul>
</ul> or an enum with a valid integer tag type.
<p>
TODO right now bool is not accepted. Also I think we could make non powers of 2 work fine, maybe
we can remove this restriction
@@ -6497,7 +6735,7 @@ async fn func(y: *i32) void {
Supported operations:
</p>
<ul>
<li>{#syntax#}.Xchg{#endsyntax#} - stores the operand unmodified.</li>
<li>{#syntax#}.Xchg{#endsyntax#} - stores the operand unmodified. Supports enums, integers and floats.</li>
<li>{#syntax#}.Add{#endsyntax#} - for integers, twos complement wraparound addition.
Also supports {#link|Floats#}.</li>
<li>{#syntax#}.Sub{#endsyntax#} - for integers, twos complement wraparound subtraction.
@@ -6510,13 +6748,32 @@ async fn func(y: *i32) void {
<li>{#syntax#}.Min{#endsyntax#} - stores the operand if it is smaller. Supports integers and floats.</li>
</ul>
{#header_close#}
{#header_open|@atomicStore#}
<pre>{#syntax#}@atomicStore(comptime T: type, ptr: *T, value: T, comptime ordering: builtin.AtomicOrder) void{#endsyntax#}</pre>
<p>
This builtin function atomically stores a value.
</p>
<p>
{#syntax#}T{#endsyntax#} must be a pointer type, a {#syntax#}bool{#endsyntax#}, a float,
an integer whose bit count meets these requirements:
</p>
<ul>
<li>At least 8</li>
<li>At most the same as usize</li>
<li>Power of 2</li>
</ul> or an enum with a valid integer tag type.
<p>
TODO right now bool is not accepted. Also I think we could make non powers of 2 work fine, maybe
we can remove this restriction
</p>
{#header_close#}
{#header_open|@bitCast#}
<pre>{#syntax#}@bitCast(comptime DestType: type, value: var) DestType{#endsyntax#}</pre>
<p>
Converts a value of one type to another type.
</p>
<p>
Asserts that {#syntax#}@sizeOf(@typeOf(value)) == @sizeOf(DestType){#endsyntax#}.
Asserts that {#syntax#}@sizeOf(@TypeOf(value)) == @sizeOf(DestType){#endsyntax#}.
</p>
<p>
Asserts that {#syntax#}@typeId(DestType) != @import("builtin").TypeId.Pointer{#endsyntax#}. Use {#syntax#}@ptrCast{#endsyntax#} or {#syntax#}@intToPtr{#endsyntax#} if you need this.
@@ -6572,9 +6829,12 @@ async fn func(y: *i32) void {
{#header_open|@mulAdd#}
<pre>{#syntax#}@mulAdd(comptime T: type, a: T, b: T, c: T) T{#endsyntax#}</pre>
<p>
Fused multiply add (for floats), similar to {#syntax#}(a * b) + c{#endsyntax#}, except
Fused multiply add, similar to {#syntax#}(a * b) + c{#endsyntax#}, except
only rounds once, and is thus more accurate.
</p>
<p>
Supports Floats and Vectors of floats.
</p>
{#header_close#}
{#header_open|@byteSwap#}
@@ -6627,6 +6887,102 @@ async fn func(y: *i32) void {
</p>
{#header_close#}
{#header_open|@call#}
<pre>{#syntax#}@call(options: std.builtin.CallOptions, function: var, args: var) var{#endsyntax#}</pre>
<p>
Calls a function, in the same way that invoking an expression with parentheses does:
</p>
{#code_begin|test|call#}
const assert = @import("std").debug.assert;
test "noinline function call" {
assert(@call(.{}, add, .{3, 9}) == 12);
}
fn add(a: i32, b: i32) i32 {
return a + b;
}
{#code_end#}
<p>
{#syntax#}@call{#endsyntax#} allows more flexibility than normal function call syntax does. The
{#syntax#}CallOptions{#endsyntax#} struct is reproduced here:
</p>
{#code_begin|syntax#}
pub const CallOptions = struct {
modifier: Modifier = .auto,
stack: ?[]align(std.Target.stack_align) u8 = null,
pub const Modifier = enum {
/// Equivalent to function call syntax.
auto,
/// Equivalent to async keyword used with function call syntax.
async_kw,
/// Prevents tail call optimization. This guarantees that the return
/// address will point to the callsite, as opposed to the callsite's
/// callsite. If the call is otherwise required to be tail-called
/// or inlined, a compile error is emitted instead.
never_tail,
/// Guarantees that the call will not be inlined. If the call is
/// otherwise required to be inlined, a compile error is emitted instead.
never_inline,
/// Asserts that the function call will not suspend. This allows a
/// non-async function to call an async function.
no_async,
/// Guarantees that the call will be generated with tail call optimization.
/// If this is not possible, a compile error is emitted instead.
always_tail,
/// Guarantees that the call will inlined at the callsite.
/// If this is not possible, a compile error is emitted instead.
always_inline,
/// Evaluates the call at compile-time. If the call cannot be completed at
/// compile-time, a compile error is emitted instead.
compile_time,
};
};
{#code_end#}
{#header_open|Calling with a New Stack#}
<p>
When the {#syntax#}stack{#endsyntax#} option is provided, instead of using the same stack as the caller, the function uses the provided stack.
</p>
{#code_begin|test|new_stack_call#}
const std = @import("std");
const assert = std.debug.assert;
var new_stack_bytes: [1024]u8 align(16) = undefined;
test "calling a function with a new stack" {
const arg = 1234;
const a = @call(.{.stack = new_stack_bytes[0..512]}, targetFunction, .{arg});
const b = @call(.{.stack = new_stack_bytes[512..]}, targetFunction, .{arg});
_ = targetFunction(arg);
assert(arg == 1234);
assert(a < b);
}
fn targetFunction(x: i32) usize {
assert(x == 1234);
var local_variable: i32 = 42;
const ptr = &local_variable;
ptr.* += 1;
assert(local_variable == 43);
return @ptrToInt(ptr);
}
{#code_end#}
{#header_close#}
{#header_close#}
{#header_open|@cDefine#}
<pre>{#syntax#}@cDefine(comptime name: []u8, value){#endsyntax#}</pre>
<p>
@@ -6677,7 +7033,7 @@ async fn func(y: *i32) void {
This function can only occur inside {#syntax#}@cImport{#endsyntax#}.
</p>
<p>
This appends <code>#include <$path>\n</code> to the {#syntax#}c_import{#endsyntax#}
This appends <code>#include &lt;$path&gt;\n</code> to the {#syntax#}c_import{#endsyntax#}
temporary buffer.
</p>
{#see_also|Import from C Header File|@cImport|@cDefine|@cUndef#}
@@ -6725,7 +7081,7 @@ fn cmpxchgStrongButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_v
<p>
{#syntax#}AtomicOrder{#endsyntax#} can be found with {#syntax#}@import("builtin").AtomicOrder{#endsyntax#}.
</p>
<p>{#syntax#}@typeOf(ptr).alignment{#endsyntax#} must be {#syntax#}>= @sizeOf(T).{#endsyntax#}</p>
<p>{#syntax#}@TypeOf(ptr).alignment{#endsyntax#} must be {#syntax#}>= @sizeOf(T).{#endsyntax#}</p>
{#see_also|Compile Variables|cmpxchgWeak#}
{#header_close#}
{#header_open|@cmpxchgWeak#}
@@ -6753,7 +7109,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val
<p>
{#syntax#}AtomicOrder{#endsyntax#} can be found with {#syntax#}@import("builtin").AtomicOrder{#endsyntax#}.
</p>
<p>{#syntax#}@typeOf(ptr).alignment{#endsyntax#} must be {#syntax#}>= @sizeOf(T).{#endsyntax#}</p>
<p>{#syntax#}@TypeOf(ptr).alignment{#endsyntax#} must be {#syntax#}>= @sizeOf(T).{#endsyntax#}</p>
{#see_also|Compile Variables|cmpxchgStrong#}
{#header_close#}
@@ -6798,10 +7154,9 @@ const num1 = blk: {
test "main" {
@compileLog("comptime in main");
warn("Runtime in main, num1 = {}.\n", num1);
warn("Runtime in main, num1 = {}.\n", .{num1});
}
{#code_end#}
</p>
<p>
will ouput:
</p>
@@ -6820,7 +7175,7 @@ const num1 = blk: {
};
test "main" {
warn("Runtime in main, num1 = {}.\n", num1);
warn("Runtime in main, num1 = {}.\n", .{num1});
}
{#code_end#}
{#header_close#}
@@ -6973,21 +7328,21 @@ test "main" {
{#header_close#}
{#header_open|@export#}
<pre>{#syntax#}@export(comptime name: []const u8, target: var, linkage: builtin.GlobalLinkage) void{#endsyntax#}</pre>
<pre>{#syntax#}@export(target: var, comptime options: std.builtin.ExportOptions) void{#endsyntax#}</pre>
<p>
Creates a symbol in the output object file.
</p>
<p>
This function can be called from a {#link|comptime#} block to conditionally export symbols.
When {#syntax#}target{#endsyntax#} is a function with the C calling convention and
{#syntax#}linkage{#endsyntax#} is {#syntax#}Strong{#endsyntax#}, this is equivalent to
{#syntax#}options.linkage{#endsyntax#} is {#syntax#}Strong{#endsyntax#}, this is equivalent to
the {#syntax#}export{#endsyntax#} keyword used on a function:
</p>
{#code_begin|obj#}
const builtin = @import("builtin");
comptime {
@export("foo", internalName, builtin.GlobalLinkage.Strong);
@export(internalName, .{ .name = "foo", .linkage = .Strong });
}
extern fn internalName() void {}
@@ -7077,7 +7432,7 @@ test "field access by string" {
<pre>{#syntax#}@frame() *@Frame(func){#endsyntax#}</pre>
<p>
This function returns a pointer to the frame for a given function. This type
can be {#link|implicitly cast|Implicit Casts#} to {#syntax#}anyframe->T{#endsyntax#} and
can be {#link|coerced|Type Coercion#} to {#syntax#}anyframe->T{#endsyntax#} and
to {#syntax#}anyframe{#endsyntax#}, where {#syntax#}T{#endsyntax#} is the return type
of the function in scope.
</p>
@@ -7101,7 +7456,7 @@ test "field access by string" {
const std = @import("std");
test "heap allocated frame" {
const frame = try std.heap.direct_allocator.create(@Frame(func));
const frame = try std.heap.page_allocator.create(@Frame(func));
frame.* = async func();
}
@@ -7213,27 +7568,6 @@ test "@hasDecl" {
{#see_also|Compile Variables|@embedFile#}
{#header_close#}
{#header_open|@inlineCall#}
<pre>{#syntax#}@inlineCall(function: X, args: ...) Y{#endsyntax#}</pre>
<p>
This calls a function, in the same way that invoking an expression with parentheses does:
</p>
{#code_begin|test#}
const assert = @import("std").debug.assert;
test "inline function call" {
assert(@inlineCall(add, 3, 9) == 12);
}
fn add(a: i32, b: i32) i32 { return a + b; }
{#code_end#}
<p>
Unlike a normal function call, however, {#syntax#}@inlineCall{#endsyntax#} guarantees that the call
will be inlined. If the call cannot be inlined, a compile error is emitted.
</p>
{#see_also|@noInlineCall#}
{#header_close#}
{#header_open|@intCast#}
<pre>{#syntax#}@intCast(comptime DestType: type, int: var) DestType{#endsyntax#}</pre>
<p>
@@ -7241,6 +7575,10 @@ fn add(a: i32, b: i32) i32 { return a + b; }
Attempting to convert a number which is out of range of the destination type results in
safety-protected {#link|Undefined Behavior#}.
</p>
<p>
If {#syntax#}T{#endsyntax#} is {#syntax#}comptime_int{#endsyntax#},
then this is semantically equivalent to {#link|Type Coercion#}.
</p>
{#header_close#}
{#header_open|@intToEnum#}
@@ -7387,71 +7725,6 @@ mem.set(u8, dest, c);{#endsyntax#}</pre>
</p>
{#header_close#}
{#header_open|@newStackCall#}
<pre>{#syntax#}@newStackCall(new_stack: []align(target_stack_align) u8, function: var, args: ...) var{#endsyntax#}</pre>
<p>
This calls a function, in the same way that invoking an expression with parentheses does. However,
instead of using the same stack as the caller, the function uses the stack provided in the {#syntax#}new_stack{#endsyntax#}
parameter.
</p>
<p>
The new stack must be aligned to {#syntax#}target_stack_align{#endsyntax#} bytes. This is a target-specific
number. A safe value that will work on all targets is {#syntax#}16{#endsyntax#}. This value can
also be obtained by using {#link|@sizeOf#} on the {#link|@Frame#} type of {#link|Async Functions#}.
</p>
{#code_begin|test#}
const std = @import("std");
const assert = std.debug.assert;
var new_stack_bytes: [1024]u8 align(16) = undefined;
test "calling a function with a new stack" {
const arg = 1234;
const a = @newStackCall(new_stack_bytes[0..512], targetFunction, arg);
const b = @newStackCall(new_stack_bytes[512..], targetFunction, arg);
_ = targetFunction(arg);
assert(arg == 1234);
assert(a < b);
}
fn targetFunction(x: i32) usize {
assert(x == 1234);
var local_variable: i32 = 42;
const ptr = &local_variable;
ptr.* += 1;
assert(local_variable == 43);
return @ptrToInt(ptr);
}
{#code_end#}
{#header_close#}
{#header_open|@noInlineCall#}
<pre>{#syntax#}@noInlineCall(function: var, args: ...) var{#endsyntax#}</pre>
<p>
This calls a function, in the same way that invoking an expression with parentheses does:
</p>
{#code_begin|test#}
const assert = @import("std").debug.assert;
test "noinline function call" {
assert(@noInlineCall(add, 3, 9) == 12);
}
fn add(a: i32, b: i32) i32 {
return a + b;
}
{#code_end#}
<p>
Unlike a normal function call, however, {#syntax#}@noInlineCall{#endsyntax#} guarantees that the call
will not be inlined. If the call must be inlined, a compile error is emitted.
</p>
{#see_also|@inlineCall#}
{#header_close#}
{#header_open|@OpaqueType#}
<pre>{#syntax#}@OpaqueType() type{#endsyntax#}</pre>
<p>
@@ -7466,7 +7739,7 @@ const Derp = @OpaqueType();
const Wat = @OpaqueType();
extern fn bar(d: *Derp) void;
export fn foo(w: *Wat) void {
fn foo(w: *Wat) callconv(.C) void {
bar(w);
}
@@ -7729,7 +8002,7 @@ test "@setRuntimeSafety" {
{#syntax#}b{#endsyntax#}. Positive numbers select from {#syntax#}a{#endsyntax#} starting at 0.
Negative values select from {#syntax#}b{#endsyntax#}, starting at {#syntax#}-1{#endsyntax#} and going down.
It is recommended to use the {#syntax#}~{#endsyntax#} operator from indexes from {#syntax#}b{#endsyntax#}
so that both indexes can start from {#syntax#}0{#endsyntax#} (i.e. {#syntax#}~i32(0){#endsyntax#} is
so that both indexes can start from {#syntax#}0{#endsyntax#} (i.e. {#syntax#}~@as(i32, 0){#endsyntax#} is
{#syntax#}-1{#endsyntax#}).
</p>
<p>
@@ -7783,7 +8056,7 @@ test "@setRuntimeSafety" {
{#header_close#}
{#header_open|@splat#}
<pre>{#syntax#}@splat(comptime len: u32, scalar: var) @Vector(len, @typeOf(scalar)){#endsyntax#}</pre>
<pre>{#syntax#}@splat(comptime len: u32, scalar: var) @Vector(len, @TypeOf(scalar)){#endsyntax#}</pre>
<p>
Produces a vector of length {#syntax#}len{#endsyntax#} where each element is the value
{#syntax#}scalar{#endsyntax#}:
@@ -7795,8 +8068,8 @@ const assert = std.debug.assert;
test "vector @splat" {
const scalar: u32 = 5;
const result = @splat(4, scalar);
comptime assert(@typeOf(result) == @Vector(4, u32));
assert(std.mem.eql(u32, ([4]u32)(result), [_]u32{ 5, 5, 5, 5 }));
comptime assert(@TypeOf(result) == @Vector(4, u32));
assert(std.mem.eql(u32, &@as([4]u32, result), &[_]u32{ 5, 5, 5, 5 }));
}
{#code_end#}
<p>
@@ -7807,94 +8080,146 @@ test "vector @splat" {
{#header_close#}
{#header_open|@sqrt#}
<pre>{#syntax#}@sqrt(comptime T: type, value: T) T{#endsyntax#}</pre>
<pre>{#syntax#}@sqrt(value: var) @TypeOf(value){#endsyntax#}</pre>
<p>
Performs the square root of a floating point number. Uses a dedicated hardware instruction
when available. Supports {#syntax#}f16{#endsyntax#}, {#syntax#}f32{#endsyntax#}, {#syntax#}f64{#endsyntax#}, and {#syntax#}f128{#endsyntax#}, as well as vectors.
when available.
</p>
<p>
Supports {#link|Floats#} and {#link|Vectors#} of floats, with the caveat that
<a href="https://github.com/ziglang/zig/issues/4026">some float operations are not yet implemented for all float types</a>.
</p>
{#header_close#}
{#header_open|@sin#}
<pre>{#syntax#}@sin(comptime T: type, value: T) T{#endsyntax#}</pre>
<pre>{#syntax#}@sin(value: var) @TypeOf(value){#endsyntax#}</pre>
<p>
Sine trigometric function on a floating point number. Uses a dedicated hardware instruction
when available. Currently supports {#syntax#}f32{#endsyntax#} and {#syntax#}f64{#endsyntax#}.
when available.
</p>
<p>
Supports {#link|Floats#} and {#link|Vectors#} of floats, with the caveat that
<a href="https://github.com/ziglang/zig/issues/4026">some float operations are not yet implemented for all float types</a>.
</p>
{#header_close#}
{#header_open|@cos#}
<pre>{#syntax#}@cos(comptime T: type, value: T) T{#endsyntax#}</pre>
<pre>{#syntax#}@cos(value: var) @TypeOf(value){#endsyntax#}</pre>
<p>
Cosine trigometric function on a floating point number. Uses a dedicated hardware instruction
when available. Currently supports {#syntax#}f32{#endsyntax#} and {#syntax#}f64{#endsyntax#}.
when available.
</p>
<p>
Supports {#link|Floats#} and {#link|Vectors#} of floats, with the caveat that
<a href="https://github.com/ziglang/zig/issues/4026">some float operations are not yet implemented for all float types</a>.
</p>
{#header_close#}
{#header_open|@exp#}
<pre>{#syntax#}@exp(comptime T: type, value: T) T{#endsyntax#}</pre>
<pre>{#syntax#}@exp(value: var) @TypeOf(value){#endsyntax#}</pre>
<p>
Base-e exponential function on a floating point number. Uses a dedicated hardware instruction
when available. Currently supports {#syntax#}f32{#endsyntax#} and {#syntax#}f64{#endsyntax#}.
when available.
</p>
<p>
Supports {#link|Floats#} and {#link|Vectors#} of floats, with the caveat that
<a href="https://github.com/ziglang/zig/issues/4026">some float operations are not yet implemented for all float types</a>.
</p>
{#header_close#}
{#header_open|@exp2#}
<pre>{#syntax#}@exp2(comptime T: type, value: T) T{#endsyntax#}</pre>
<pre>{#syntax#}@exp2(value: var) @TypeOf(value){#endsyntax#}</pre>
<p>
Base-2 exponential function on a floating point number. Uses a dedicated hardware instruction
when available. Currently supports {#syntax#}f32{#endsyntax#} and {#syntax#}f64{#endsyntax#}.
when available.
</p>
<p>
Supports {#link|Floats#} and {#link|Vectors#} of floats, with the caveat that
<a href="https://github.com/ziglang/zig/issues/4026">some float operations are not yet implemented for all float types</a>.
</p>
{#header_close#}
{#header_open|@ln#}
<pre>{#syntax#}@ln(comptime T: type, value: T) T{#endsyntax#}</pre>
{#header_open|@log#}
<pre>{#syntax#}@log(value: var) @TypeOf(value){#endsyntax#}</pre>
<p>
Returns the natural logarithm of a floating point number. Uses a dedicated hardware instruction
when available. Currently supports {#syntax#}f32{#endsyntax#} and {#syntax#}f64{#endsyntax#}.
when available.
</p>
<p>
Supports {#link|Floats#} and {#link|Vectors#} of floats, with the caveat that
<a href="https://github.com/ziglang/zig/issues/4026">some float operations are not yet implemented for all float types</a>.
</p>
{#header_close#}
{#header_open|@log2#}
<pre>{#syntax#}@log2(comptime T: type, value: T) T{#endsyntax#}</pre>
<pre>{#syntax#}@log2(value: var) @TypeOf(value){#endsyntax#}</pre>
<p>
Returns the logarithm to the base 2 of a floating point number. Uses a dedicated hardware instruction
when available. Currently supports {#syntax#}f32{#endsyntax#} and {#syntax#}f64{#endsyntax#}.
when available.
</p>
<p>
Supports {#link|Floats#} and {#link|Vectors#} of floats, with the caveat that
<a href="https://github.com/ziglang/zig/issues/4026">some float operations are not yet implemented for all float types</a>.
</p>
{#header_close#}
{#header_open|@log10#}
<pre>{#syntax#}@log10(comptime T: type, value: T) T{#endsyntax#}</pre>
<pre>{#syntax#}@log10(value: var) @TypeOf(value){#endsyntax#}</pre>
<p>
Returns the logarithm to the base 10 of a floating point number. Uses a dedicated hardware instruction
when available. Currently supports {#syntax#}f32{#endsyntax#} and {#syntax#}f64{#endsyntax#}.
when available.
</p>
<p>
Supports {#link|Floats#} and {#link|Vectors#} of floats, with the caveat that
<a href="https://github.com/ziglang/zig/issues/4026">some float operations are not yet implemented for all float types</a>.
</p>
{#header_close#}
{#header_open|@fabs#}
<pre>{#syntax#}@fabs(comptime T: type, value: T) T{#endsyntax#}</pre>
<pre>{#syntax#}@fabs(value: var) @TypeOf(value){#endsyntax#}</pre>
<p>
Returns the absolute value of a floating point number. Uses a dedicated hardware instruction
when available. Currently supports {#syntax#}f32{#endsyntax#} and {#syntax#}f64{#endsyntax#}.
when available.
</p>
<p>
Supports {#link|Floats#} and {#link|Vectors#} of floats, with the caveat that
<a href="https://github.com/ziglang/zig/issues/4026">some float operations are not yet implemented for all float types</a>.
</p>
{#header_close#}
{#header_open|@floor#}
<pre>{#syntax#}@floor(comptime T: type, value: T) T{#endsyntax#}</pre>
<pre>{#syntax#}@floor(value: var) @TypeOf(value){#endsyntax#}</pre>
<p>
Returns the largest integral value not greater than the given floating point number. Uses a dedicated hardware instruction
when available. Currently supports {#syntax#}f32{#endsyntax#} and {#syntax#}f64{#endsyntax#}.
Returns the largest integral value not greater than the given floating point number.
Uses a dedicated hardware instruction when available.
</p>
<p>
Supports {#link|Floats#} and {#link|Vectors#} of floats, with the caveat that
<a href="https://github.com/ziglang/zig/issues/4026">some float operations are not yet implemented for all float types</a>.
</p>
{#header_close#}
{#header_open|@ceil#}
<pre>{#syntax#}@ceil(comptime T: type, value: T) T{#endsyntax#}</pre>
<pre>{#syntax#}@ceil(value: var) @TypeOf(value){#endsyntax#}</pre>
<p>
Returns the largest integral value not less than the given floating point number. Uses a dedicated hardware instruction
when available. Currently supports {#syntax#}f32{#endsyntax#} and {#syntax#}f64{#endsyntax#}.
Returns the largest integral value not less than the given floating point number.
Uses a dedicated hardware instruction when available.
</p>
<p>
Supports {#link|Floats#} and {#link|Vectors#} of floats, with the caveat that
<a href="https://github.com/ziglang/zig/issues/4026">some float operations are not yet implemented for all float types</a>.
</p>
{#header_close#}
{#header_open|@trunc#}
<pre>{#syntax#}@trunc(comptime T: type, value: T) T{#endsyntax#}</pre>
<pre>{#syntax#}@trunc(value: var) @TypeOf(value){#endsyntax#}</pre>
<p>
Rounds the given floating point number to an integer, towards zero. Uses a dedicated hardware instruction
when available. Currently supports {#syntax#}f32{#endsyntax#} and {#syntax#}f64{#endsyntax#}.
Rounds the given floating point number to an integer, towards zero.
Uses a dedicated hardware instruction when available.
</p>
<p>
Supports {#link|Floats#} and {#link|Vectors#} of floats, with the caveat that
<a href="https://github.com/ziglang/zig/issues/4026">some float operations are not yet implemented for all float types</a>.
</p>
{#header_close#}
{#header_open|@round#}
<pre>{#syntax#}@round(comptime T: type, value: T) T{#endsyntax#}</pre>
<pre>{#syntax#}@round(value: var) @TypeOf(value){#endsyntax#}</pre>
<p>
Rounds the given floating point number to an integer, away from zero. Uses a dedicated hardware instruction
when available. Currently supports {#syntax#}f32{#endsyntax#} and {#syntax#}f64{#endsyntax#}.
when available.
</p>
<p>
Supports {#link|Floats#} and {#link|Vectors#} of floats, with the caveat that
<a href="https://github.com/ziglang/zig/issues/4026">some float operations are not yet implemented for all float types</a>.
</p>
{#header_close#}
@@ -7992,10 +8317,6 @@ test "integer truncation" {
This function always truncates the significant bits of the integer, regardless
of endianness on the target platform.
</p>
<p>
If {#syntax#}T{#endsyntax#} is {#syntax#}comptime_int{#endsyntax#},
then this is semantically equivalent to an {#link|implicit cast|Implicit Casts#}.
</p>
{#header_close#}
{#header_open|@Type#}
@@ -8012,13 +8333,13 @@ test "integer truncation" {
<li>{#syntax#}noreturn{#endsyntax#}</li>
<li>{#syntax#}void{#endsyntax#}</li>
<li>{#syntax#}bool{#endsyntax#}</li>
<li>{#link|Integers#}</li> - The maximum bit count for an integer type is {#syntax#}65535{#endsyntax#}.
<li>{#link|Integers#} - The maximum bit count for an integer type is {#syntax#}65535{#endsyntax#}.</li>
<li>{#link|Floats#}</li>
<li>{#link|Pointers#}</li>
<li>{#syntax#}comptime_int{#endsyntax#}</li>
<li>{#syntax#}comptime_float{#endsyntax#}</li>
<li>{#syntax#}@typeOf(undefined){#endsyntax#}</li>
<li>{#syntax#}@typeOf(null){#endsyntax#}</li>
<li>{#syntax#}@TypeOf(undefined){#endsyntax#}</li>
<li>{#syntax#}@TypeOf(null){#endsyntax#}</li>
</ul>
<p>
For these types it is a
@@ -8044,7 +8365,6 @@ test "integer truncation" {
<li>{#link|union#}</li>
<li>{#link|Functions#}</li>
<li>BoundFn</li>
<li>ArgTuple</li>
<li>{#link|struct#}</li>
</ul>
{#header_close#}
@@ -8071,205 +8391,25 @@ pub const TypeId = enum {
Null,
Optional,
ErrorUnion,
Error,
ErrorSet,
Enum,
Union,
Fn,
Block,
BoundFn,
ArgTuple,
Opaque,
Frame,
AnyFrame,
Vector,
EnumLiteral,
};
{#code_end#}
{#header_close#}
{#header_open|@typeInfo#}
<pre>{#syntax#}@typeInfo(comptime T: type) @import("builtin").TypeInfo{#endsyntax#}</pre>
<pre>{#syntax#}@typeInfo(comptime T: type) @import("std").builtin.TypeInfo{#endsyntax#}</pre>
<p>
Returns information on the type. Returns a value of the following union:
Provides type reflection.
</p>
{#code_begin|syntax#}
pub const TypeInfo = union(TypeId) {
Type: void,
Void: void,
Bool: void,
NoReturn: void,
Int: Int,
Float: Float,
Pointer: Pointer,
Array: Array,
Struct: Struct,
ComptimeFloat: void,
ComptimeInt: void,
Undefined: void,
Null: void,
Optional: Optional,
ErrorUnion: ErrorUnion,
ErrorSet: ErrorSet,
Enum: Enum,
Union: Union,
Fn: Fn,
BoundFn: Fn,
ArgTuple: void,
Opaque: void,
Promise: Promise,
Vector: Vector,
EnumLiteral: void,
pub const Int = struct {
is_signed: bool,
bits: comptime_int,
};
pub const Float = struct {
bits: comptime_int,
};
pub const Pointer = struct {
size: Size,
is_const: bool,
is_volatile: bool,
alignment: comptime_int,
child: type,
is_allowzero: bool,
pub const Size = enum {
One,
Many,
Slice,
C,
};
};
pub const Array = struct {
len: comptime_int,
child: type,
};
pub const ContainerLayout = enum {
Auto,
Extern,
Packed,
};
pub const StructField = struct {
name: []const u8,
offset: ?comptime_int,
field_type: type,
};
pub const Struct = struct {
layout: ContainerLayout,
fields: []StructField,
decls: []Declaration,
};
pub const Optional = struct {
child: type,
};
pub const ErrorUnion = struct {
error_set: type,
payload: type,
};
pub const Error = struct {
name: []const u8,
value: comptime_int,
};
pub const ErrorSet = ?[]Error;
pub const EnumField = struct {
name: []const u8,
value: comptime_int,
};
pub const Enum = struct {
layout: ContainerLayout,
tag_type: type,
fields: []EnumField,
decls: []Declaration,
};
pub const UnionField = struct {
name: []const u8,
enum_field: ?EnumField,
field_type: type,
};
pub const Union = struct {
layout: ContainerLayout,
tag_type: ?type,
fields: []UnionField,
decls: []Declaration,
};
pub const CallingConvention = enum {
Unspecified,
C,
Cold,
Naked,
Stdcall,
Async,
};
pub const FnArg = struct {
is_generic: bool,
is_noalias: bool,
arg_type: ?type,
};
pub const Fn = struct {
calling_convention: CallingConvention,
is_generic: bool,
is_var_args: bool,
return_type: ?type,
async_allocator_type: ?type,
args: []FnArg,
};
pub const Promise = struct {
child: ?type,
};
pub const Vector = struct {
len: comptime_int,
child: type,
};
pub const Declaration = struct {
name: []const u8,
is_pub: bool,
data: Data,
pub const Data = union(enum) {
Type: type,
Var: type,
Fn: FnDecl,
pub const FnDecl = struct {
fn_type: type,
inline_type: Inline,
calling_convention: CallingConvention,
is_var_args: bool,
is_extern: bool,
is_export: bool,
lib_name: ?[]const u8,
return_type: type,
arg_names: [][] const u8,
pub const Inline = enum {
Auto,
Always,
Never,
};
};
};
};
};
{#code_end#}
<p>
For {#link|structs|struct#}, {#link|unions|union#}, {#link|enums|enum#}, and
{#link|error sets|Error Set Type#}, the fields are guaranteed to be in the same
@@ -8286,20 +8426,20 @@ pub const TypeInfo = union(TypeId) {
{#header_close#}
{#header_open|@typeOf#}
<pre>{#syntax#}@typeOf(expression) type{#endsyntax#}</pre>
{#header_open|@TypeOf#}
<pre>{#syntax#}@TypeOf(expression) type{#endsyntax#}</pre>
<p>
This function returns a compile-time constant, which is the type of the
expression passed as an argument. The expression is evaluated.
</p>
<p>{#syntax#}@typeOf{#endsyntax#} guarantees no run-time side-effects within the expression:</p>
<p>{#syntax#}@TypeOf{#endsyntax#} guarantees no run-time side-effects within the expression:</p>
{#code_begin|test#}
const std = @import("std");
const assert = std.debug.assert;
test "no runtime side effects" {
var data: i32 = 0;
const T = @typeOf(foo(i32, &data));
const T = @TypeOf(foo(i32, &data));
comptime assert(T == i32);
assert(data == 0);
}
@@ -8406,7 +8546,7 @@ pub fn build(b: *Builder) void {
{#header_close#}
{#header_open|Single Threaded Builds#}
<p>Zig has a compile option <code>--single-threaded</code> which has the following effects:
<p>Zig has a compile option <code>--single-threaded</code> which has the following effects:</p>
<ul>
<li>All {#link|Thread Local Variables#} are treated as {#link|Global Variables#}.</li>
<li>The overhead of {#link|Async Functions#} becomes equivalent to function call overhead.</li>
@@ -8415,7 +8555,6 @@ pub fn build(b: *Builder) void {
For example {#syntax#}std.Mutex{#endsyntax#} becomes
an empty data structure and all of its functions become no-ops.</li>
</ul>
</p>
{#header_close#}
{#header_open|Undefined Behavior#}
@@ -8459,7 +8598,7 @@ pub fn main() void {
<p>At compile-time:</p>
{#code_begin|test_err|index 5 outside array of size 5#}
comptime {
const array = "hello";
const array: [5]u8 = "hello".*;
const garbage = array[5];
}
{#code_end#}
@@ -8489,7 +8628,7 @@ const std = @import("std");
pub fn main() void {
var value: i32 = -1;
var unsigned = @intCast(u32, value);
std.debug.warn("value: {}\n", unsigned);
std.debug.warn("value: {}\n", .{unsigned});
}
{#code_end#}
<p>
@@ -8498,7 +8637,7 @@ pub fn main() void {
{#header_close#}
{#header_open|Cast Truncates Data#}
<p>At compile-time:</p>
{#code_begin|test_err|integer value 300 cannot be implicitly casted to type 'u8'#}
{#code_begin|test_err|integer value 300 cannot be coerced to type 'u8'#}
comptime {
const spartan_count: u16 = 300;
const byte = @intCast(u8, spartan_count);
@@ -8511,7 +8650,7 @@ const std = @import("std");
pub fn main() void {
var spartan_count: u16 = 300;
const byte = @intCast(u8, spartan_count);
std.debug.warn("value: {}\n", byte);
std.debug.warn("value: {}\n", .{byte});
}
{#code_end#}
<p>
@@ -8545,7 +8684,7 @@ const std = @import("std");
pub fn main() void {
var byte: u8 = 255;
byte += 1;
std.debug.warn("value: {}\n", byte);
std.debug.warn("value: {}\n", .{byte});
}
{#code_end#}
{#header_close#}
@@ -8568,11 +8707,11 @@ pub fn main() !void {
var byte: u8 = 255;
byte = if (math.add(u8, byte, 1)) |result| result else |err| {
warn("unable to add one: {}\n", @errorName(err));
warn("unable to add one: {}\n", .{@errorName(err)});
return err;
};
warn("result: {}\n", byte);
warn("result: {}\n", .{byte});
}
{#code_end#}
{#header_close#}
@@ -8597,9 +8736,9 @@ pub fn main() void {
var result: u8 = undefined;
if (@addWithOverflow(u8, byte, 10, &result)) {
warn("overflowed result: {}\n", result);
warn("overflowed result: {}\n", .{result});
} else {
warn("result: {}\n", result);
warn("result: {}\n", .{result});
}
}
{#code_end#}
@@ -8634,7 +8773,7 @@ test "wraparound addition and subtraction" {
<p>At compile-time:</p>
{#code_begin|test_err|operation caused overflow#}
comptime {
const x = @shlExact(u8(0b01010101), 2);
const x = @shlExact(@as(u8, 0b01010101), 2);
}
{#code_end#}
<p>At runtime:</p>
@@ -8644,7 +8783,7 @@ const std = @import("std");
pub fn main() void {
var x: u8 = 0b01010101;
var y = @shlExact(x, 2);
std.debug.warn("value: {}\n", y);
std.debug.warn("value: {}\n", .{y});
}
{#code_end#}
{#header_close#}
@@ -8652,7 +8791,7 @@ pub fn main() void {
<p>At compile-time:</p>
{#code_begin|test_err|exact shift shifted out 1 bits#}
comptime {
const x = @shrExact(u8(0b10101010), 2);
const x = @shrExact(@as(u8, 0b10101010), 2);
}
{#code_end#}
<p>At runtime:</p>
@@ -8662,7 +8801,7 @@ const std = @import("std");
pub fn main() void {
var x: u8 = 0b10101010;
var y = @shrExact(x, 2);
std.debug.warn("value: {}\n", y);
std.debug.warn("value: {}\n", .{y});
}
{#code_end#}
{#header_close#}
@@ -8683,7 +8822,7 @@ pub fn main() void {
var a: u32 = 1;
var b: u32 = 0;
var c = a / b;
std.debug.warn("value: {}\n", c);
std.debug.warn("value: {}\n", .{c});
}
{#code_end#}
{#header_close#}
@@ -8704,7 +8843,7 @@ pub fn main() void {
var a: u32 = 10;
var b: u32 = 0;
var c = a % b;
std.debug.warn("value: {}\n", c);
std.debug.warn("value: {}\n", .{c});
}
{#code_end#}
{#header_close#}
@@ -8725,7 +8864,7 @@ pub fn main() void {
var a: u32 = 10;
var b: u32 = 3;
var c = @divExact(a, b);
std.debug.warn("value: {}\n", c);
std.debug.warn("value: {}\n", .{c});
}
{#code_end#}
{#header_close#}
@@ -8734,7 +8873,7 @@ pub fn main() void {
{#code_begin|test_err|unable to convert#}
comptime {
var bytes = [5]u8{ 1, 2, 3, 4, 5 };
var slice = @bytesToSlice(u32, bytes);
var slice = @bytesToSlice(u32, bytes[0..]);
}
{#code_end#}
<p>At runtime:</p>
@@ -8744,7 +8883,7 @@ const std = @import("std");
pub fn main() void {
var bytes = [5]u8{ 1, 2, 3, 4, 5 };
var slice = @bytesToSlice(u32, bytes[0..]);
std.debug.warn("value: {}\n", slice[0]);
std.debug.warn("value: {}\n", .{slice[0]});
}
{#code_end#}
{#header_close#}
@@ -8763,7 +8902,7 @@ const std = @import("std");
pub fn main() void {
var optional_number: ?i32 = null;
var number = optional_number.?;
std.debug.warn("value: {}\n", number);
std.debug.warn("value: {}\n", .{number});
}
{#code_end#}
<p>One way to avoid this crash is to test for null instead of assuming non-null, with
@@ -8774,9 +8913,9 @@ pub fn main() void {
const optional_number: ?i32 = null;
if (optional_number) |number| {
warn("got number: {}\n", number);
warn("got number: {}\n", .{number});
} else {
warn("it's null\n");
warn("it's null\n", .{});
}
}
{#code_end#}
@@ -8799,7 +8938,7 @@ const std = @import("std");
pub fn main() void {
const number = getNumberOrFail() catch unreachable;
std.debug.warn("value: {}\n", number);
std.debug.warn("value: {}\n", .{number});
}
fn getNumberOrFail() !i32 {
@@ -8815,9 +8954,9 @@ pub fn main() void {
const result = getNumberOrFail();
if (result) |number| {
warn("got number: {}\n", number);
warn("got number: {}\n", .{number});
} else |err| {
warn("got error: {}\n", @errorName(err));
warn("got error: {}\n", .{@errorName(err)});
}
}
@@ -8844,7 +8983,7 @@ pub fn main() void {
var err = error.AnError;
var number = @errorToInt(err) + 500;
var invalid_err = @intToError(number);
std.debug.warn("value: {}\n", number);
std.debug.warn("value: {}\n", .{number});
}
{#code_end#}
{#header_close#}
@@ -8874,7 +9013,7 @@ const Foo = enum {
pub fn main() void {
var a: u2 = 3;
var b = @intToEnum(Foo, a);
std.debug.warn("value: {}\n", @tagName(b));
std.debug.warn("value: {}\n", .{@tagName(b)});
}
{#code_end#}
{#header_close#}
@@ -8911,7 +9050,7 @@ pub fn main() void {
}
fn foo(set1: Set1) void {
const x = @errSetCast(Set2, set1);
std.debug.warn("value: {}\n", x);
std.debug.warn("value: {}\n", .{x});
}
{#code_end#}
{#header_close#}
@@ -8920,7 +9059,7 @@ fn foo(set1: Set1) void {
<p>At compile-time:</p>
{#code_begin|test_err|pointer address 0x1 is not aligned to 4 bytes#}
comptime {
const ptr = @intToPtr(*i32, 0x1);
const ptr = @intToPtr(*align(1) i32, 0x1);
const aligned = @alignCast(4, ptr);
}
{#code_end#}
@@ -8967,7 +9106,7 @@ pub fn main() void {
fn bar(f: *Foo) void {
f.float = 12.34;
std.debug.warn("value: {}\n", f.float);
std.debug.warn("value: {}\n", .{f.float});
}
{#code_end#}
<p>
@@ -8991,7 +9130,7 @@ pub fn main() void {
fn bar(f: *Foo) void {
f.* = Foo{ .float = 12.34 };
std.debug.warn("value: {}\n", f.float);
std.debug.warn("value: {}\n", .{f.float});
}
{#code_end#}
<p>
@@ -9010,7 +9149,7 @@ pub fn main() void {
var f = Foo{ .int = 42 };
f = Foo{ .float = undefined };
bar(&f);
std.debug.warn("value: {}\n", f.float);
std.debug.warn("value: {}\n", .{f.float});
}
fn bar(f: *Foo) void {
@@ -9110,8 +9249,6 @@ fn concat(allocator: *Allocator, a: []const u8, b: []const u8) ![]u8 {
</li>
<li>Are you linking libc? In this case, {#syntax#}std.heap.c_allocator{#endsyntax#} is likely
the right choice, at least for your main allocator.</li>
<li>Are you building for WebAssembly? In this case, {#syntax#}std.heap.wasm_allocator{#endsyntax#} is likely
the right choice for your main allocator as it uses WebAssembly's memory instructions.</li>
<li>
Is the maximum number of bytes that you will need bounded by a number known at
{#link|comptime#}? In this case, use {#syntax#}std.heap.FixedBufferAllocator{#endsyntax#} or
@@ -9127,13 +9264,13 @@ fn concat(allocator: *Allocator, a: []const u8, b: []const u8) ![]u8 {
const std = @import("std");
pub fn main() !void {
var arena = std.heap.ArenaAllocator.init(std.heap.direct_allocator);
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer arena.deinit();
const allocator = &arena.allocator;
const ptr = try allocator.create(i32);
std.debug.warn("ptr={*}\n", ptr);
std.debug.warn("ptr={*}\n", .{ptr});
}
{#code_end#}
When using this kind of allocator, there is no need to free anything manually. Everything
@@ -9198,7 +9335,7 @@ test "string literal to constant slice" {
The location of memory allocated with {#syntax#}allocator.alloc{#endsyntax#} or
{#syntax#}allocator.create{#endsyntax#} is determined by the allocator's implementation.
</p>
</p>TODO: thread local variables</p>
<p>TODO: thread local variables</p>
{#header_close#}
{#header_open|Implementing an Allocator#}
@@ -9435,22 +9572,6 @@ test "assert in release fast mode" {
</ul>
{#see_also|Primitive Types#}
{#header_close#}
{#header_open|C String Literals#}
{#code_begin|exe#}
{#link_libc#}
extern fn puts([*]const u8) void;
pub fn main() void {
puts(c"this has a null terminator");
puts(
c\\and so
c\\does this
c\\multiline C string literal
);
}
{#code_end#}
{#see_also|String Literals and Character Literals#}
{#header_close#}
{#header_open|Import from C Header File#}
<p>
@@ -9465,7 +9586,7 @@ const c = @cImport({
@cInclude("stdio.h");
});
pub fn main() void {
_ = c.printf(c"hello\n");
_ = c.printf("hello\n");
}
{#code_end#}
<p>
@@ -9504,8 +9625,8 @@ const c = @cImport({
<p>{#syntax#}[*c]T{#endsyntax#} - C pointer.</p>
<ul>
<li>Supports all the syntax of the other two pointer types.</li>
<li>Implicitly casts to other pointer types, as well as {#link|Optional Pointers#}.
When a C pointer is implicitly casted to a non-optional pointer, safety-checked
<li>Coerces to other pointer types, as well as {#link|Optional Pointers#}.
When a C pointer is coerced to a non-optional pointer, safety-checked
{#link|Undefined Behavior#} occurs if the address is 0.
</li>
<li>Allows address 0. On non-freestanding targets, dereferencing address 0 is safety-checked
@@ -9513,7 +9634,7 @@ const c = @cImport({
null, just like {#syntax#}?usize{#endsyntax#}. Note that creating an optional C pointer
is unnecessary as one can use normal {#link|Optional Pointers#}.
</li>
<li>Supports {#link|implicit casting|Implicit Casts#} to and from integers.</li>
<li>Supports {#link|Type Coercion#} to and from integers.</li>
<li>Supports comparison with integers.</li>
<li>Does not support Zig-only pointer attributes such as alignment. Use normal {#link|Pointers#}
please!</li>
@@ -9564,7 +9685,7 @@ pub fn build(b: *Builder) void {
const lib = b.addSharedLibrary("mathtest", "mathtest.zig", b.version(1, 0, 0));
const exe = b.addExecutable("test", null);
exe.addCSourceFile("test.c", [_][]const u8{"-std=c99"});
exe.addCSourceFile("test.c", &[_][]const u8{"-std=c99"});
exe.linkLibrary(lib);
exe.linkSystemLibrary("c");
@@ -9629,7 +9750,7 @@ pub fn build(b: *Builder) void {
const obj = b.addObject("base64", "base64.zig");
const exe = b.addExecutable("test", null);
exe.addCSourceFile("test.c", [_][]const u8{"-std=c99"});
exe.addCSourceFile("test.c", &[_][]const u8{"-std=c99"});
exe.addObject(obj);
exe.linkSystemLibrary("c");
exe.install();
@@ -9643,8 +9764,7 @@ all your base are belong to us</code></pre>
{#header_close#}
{#header_close#}
{#header_open|WebAssembly#}
<p>Zig supports building for WebAssembly out of the box. There is also a specialized {#syntax#}std.heap.wasm_allocator{#endsyntax#}
memory allocator for WebAssembly environments.</p>
<p>Zig supports building for WebAssembly out of the box.</p>
{#header_open|Freestanding#}
<p>For host environments like the web browser and nodejs, build as a library using the freestanding OS target.
Here's an example of running Zig code compiled to WebAssembly with nodejs.</p>
@@ -9678,11 +9798,12 @@ The result is 3</code></pre>
const std = @import("std");
pub fn main() !void {
const args = try std.process.argsAlloc(std.heap.wasm_allocator);
defer std.process.argsFree(std.heap.wasm_allocator, args);
// TODO a better default allocator that isn't as wasteful!
const args = try std.process.argsAlloc(std.heap.page_allocator);
defer std.process.argsFree(std.heap.page_allocator, args);
for (args) |arg, i| {
std.debug.warn("{}: {}\n", i, arg);
std.debug.warn("{}: {}\n", .{i, arg});
}
}
{#code_end#}
@@ -10063,7 +10184,7 @@ fn readU32Be() u32 {}
<li>Ascii control characters, except for U+000a (LF): U+0000 - U+0009, U+000b - U+0001f, U+007f. (Note that Windows line endings (CRLF) are not allowed, and hard tabs are not allowed.)</li>
<li>Non-Ascii Unicode line endings: U+0085 (NEL), U+2028 (LS), U+2029 (PS).</li>
</ul>
<p>The codepoint U+000a (LF) (which is encoded as the single-byte value 0x0a) is the line terminator character. This character always terminates a line of zig source code (except possbly the last line of the file).</p>
<p>The codepoint U+000a (LF) (which is encoded as the single-byte value 0x0a) is the line terminator character. This character always terminates a line of zig source code (except possibly the last line of the file).</p>
<p>For some discussion on the rationale behind these design decisions, see <a href="https://github.com/ziglang/zig/issues/663">issue #663</a></p>
{#header_close#}
@@ -10087,18 +10208,18 @@ ContainerMembers
&lt;- TestDecl ContainerMembers
/ TopLevelComptime ContainerMembers
/ KEYWORD_pub? TopLevelDecl ContainerMembers
/ KEYWORD_pub? ContainerField COMMA ContainerMembers
/ KEYWORD_pub? ContainerField
/ ContainerField COMMA ContainerMembers
/ ContainerField
/
TestDecl &lt;- KEYWORD_test STRINGLITERAL Block
TestDecl &lt;- KEYWORD_test STRINGLITERALSINGLE Block
TopLevelComptime &lt;- KEYWORD_comptime BlockExpr
TopLevelDecl
&lt;- (KEYWORD_export / KEYWORD_extern STRINGLITERAL? / KEYWORD_inline)? FnProto (SEMICOLON / Block)
/ (KEYWORD_export / KEYWORD_extern STRINGLITERAL?)? KEYWORD_threadlocal? VarDecl
/ KEYWORD_use Expr SEMICOLON
&lt;- (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE? / KEYWORD_inline)? FnProto (SEMICOLON / Block)
/ (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE?)? KEYWORD_threadlocal? VarDecl
/ KEYWORD_usingnamespace Expr SEMICOLON
FnProto &lt;- FnCC? KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? LinkSection? EXCLAMATIONMARK? (KEYWORD_var / TypeExpr)
@@ -10203,6 +10324,7 @@ PrimaryTypeExpr
/ CHAR_LITERAL
/ ContainerDecl
/ DOT IDENTIFIER
/ DOT InitList
/ ErrorSetDecl
/ FLOAT
/ FnProto
@@ -10268,9 +10390,7 @@ LinkSection &lt;- KEYWORD_linksection LPAREN Expr RPAREN
# Fn specific
FnCC
&lt;- KEYWORD_nakedcc
/ KEYWORD_stdcallcc
/ KEYWORD_extern
&lt;- KEYWORD_extern
/ KEYWORD_async
ParamDecl &lt;- (KEYWORD_noalias / KEYWORD_comptime)? (IDENTIFIER COLON)? ParamType
@@ -10428,7 +10548,6 @@ string_char
line_comment &lt;- '//'[^\n]*
line_string &lt;- ("\\\\" [^\n]* [ \n]*)+
line_cstring &lt;- ("c\\\\" [^\n]* [ \n]*)+
skip &lt;- ([ \n] / line_comment)*
CHAR_LITERAL &lt;- "'" char_char "'" skip
@@ -10442,12 +10561,12 @@ INTEGER
/ "0o" [0-7]+ skip
/ "0x" hex+ skip
/ [0-9]+ skip
STRINGLITERALSINGLE &lt;- "\"" string_char* "\"" skip
STRINGLITERAL
&lt;- "c"? "\"" string_char* "\"" skip
&lt;- STRINGLITERALSINGLE
/ line_string skip
/ line_cstring skip
IDENTIFIER
&lt;- !keyword ("c" !["\\] / [A-Zabd-z_]) [A-Za-z0-9_]* skip
&lt;- !keyword [A-Za-z_] [A-Za-z0-9_]* skip
/ "@\"" string_char* "\"" skip
BUILTINIDENTIFIER &lt;- "@"[A-Za-z_][A-Za-z0-9_]* skip
@@ -10534,7 +10653,6 @@ KEYWORD_fn &lt;- 'fn' end_of_word
KEYWORD_for &lt;- 'for' end_of_word
KEYWORD_if &lt;- 'if' end_of_word
KEYWORD_inline &lt;- 'inline' end_of_word
KEYWORD_nakedcc &lt;- 'nakedcc' end_of_word
KEYWORD_noalias &lt;- 'noalias' end_of_word
KEYWORD_null &lt;- 'null' end_of_word
KEYWORD_or &lt;- 'or' end_of_word
@@ -10545,7 +10663,6 @@ KEYWORD_pub &lt;- 'pub' end_of_word
KEYWORD_resume &lt;- 'resume' end_of_word
KEYWORD_return &lt;- 'return' end_of_word
KEYWORD_linksection &lt;- 'linksection' end_of_word
KEYWORD_stdcallcc &lt;- 'stdcallcc' end_of_word
KEYWORD_struct &lt;- 'struct' end_of_word
KEYWORD_suspend &lt;- 'suspend' end_of_word
KEYWORD_switch &lt;- 'switch' end_of_word
@@ -10567,10 +10684,10 @@ keyword &lt;- KEYWORD_align / KEYWORD_and / KEYWORD_allowzero / KEYWORD_asm
/ KEYWORD_defer / KEYWORD_else / KEYWORD_enum / KEYWORD_errdefer
/ KEYWORD_error / KEYWORD_export / KEYWORD_extern / KEYWORD_false
/ KEYWORD_fn / KEYWORD_for / KEYWORD_if / KEYWORD_inline
/ KEYWORD_nakedcc / KEYWORD_noalias / KEYWORD_null / KEYWORD_or
/ KEYWORD_noalias / KEYWORD_null / KEYWORD_or
/ KEYWORD_orelse / KEYWORD_packed / KEYWORD_promise / KEYWORD_pub
/ KEYWORD_resume / KEYWORD_return / KEYWORD_linksection
/ KEYWORD_stdcallcc / KEYWORD_struct / KEYWORD_suspend
/ KEYWORD_struct / KEYWORD_suspend
/ KEYWORD_switch / KEYWORD_test / KEYWORD_threadlocal / KEYWORD_true / KEYWORD_try
/ KEYWORD_undefined / KEYWORD_union / KEYWORD_unreachable
/ KEYWORD_usingnamespace / KEYWORD_var / KEYWORD_volatile / KEYWORD_while</code></pre>
@@ -10591,6 +10708,7 @@ keyword &lt;- KEYWORD_align / KEYWORD_and / KEYWORD_allowzero / KEYWORD_asm
<li>Together we serve end users.</li>
</ul>
{#header_close#}
</div></div>
</div>
</body>
</html>
+391
View File
@@ -0,0 +1,391 @@
This file contains the copying permission notices for various files in the
GNU C Library distribution that have copyright owners other than the Free
Software Foundation. These notices all require that a copy of the notice
be included in the accompanying documentation and be distributed with
binary distributions of the code, so be sure to include this file along
with any binary distributions derived from the GNU C Library.
All code incorporated from 4.4 BSD is distributed under the following
license:
Copyright (C) 1991 Regents of the University of California.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. [This condition was removed.]
4. Neither the name of the University nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
The DNS resolver code, taken from BIND 4.9.5, is copyrighted by UC
Berkeley, by Digital Equipment Corporation and by Internet Software
Consortium. The DEC portions are under the following license:
Portions Copyright (C) 1993 by Digital Equipment Corporation.
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies, and
that the name of Digital Equipment Corporation not be used in
advertising or publicity pertaining to distribution of the document or
software without specific, written prior permission.
THE SOFTWARE IS PROVIDED ``AS IS'' AND DIGITAL EQUIPMENT CORP.
DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
The ISC portions are under the following license:
Portions Copyright (c) 1996-1999 by Internet Software Consortium.
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.
The Sun RPC support (from rpcsrc-4.0) is covered by the following
license:
Copyright (c) 2010, Oracle America, Inc.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials
provided with the distribution.
* Neither the name of the "Oracle America, Inc." nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The following CMU license covers some of the support code for Mach,
derived from Mach 3.0:
Mach Operating System
Copyright (C) 1991,1990,1989 Carnegie Mellon University
All Rights Reserved.
Permission to use, copy, modify and distribute this software and its
documentation is hereby granted, provided that both the copyright
notice and this permission notice appear in all copies of the
software, derivative works or modified versions, and any portions
thereof, and that both notices appear in supporting documentation.
CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS ``AS IS''
CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
Carnegie Mellon requests users of this software to return to
Software Distribution Coordinator
School of Computer Science
Carnegie Mellon University
Pittsburgh PA 15213-3890
or Software.Distribution@CS.CMU.EDU any improvements or
extensions that they make and grant Carnegie Mellon the rights to
redistribute these changes.
The file if_ppp.h is under the following CMU license:
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY CARNEGIE MELLON UNIVERSITY AND
CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The following license covers the files from Intel's "Highly Optimized
Mathematical Functions for Itanium" collection:
Intel License Agreement
Copyright (c) 2000, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* The name of Intel Corporation may not be used to endorse or promote
products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The files inet/getnameinfo.c and sysdeps/posix/getaddrinfo.c are copyright
(C) by Craig Metz and are distributed under the following license:
/* The Inner Net License, Version 2.00
The author(s) grant permission for redistribution and use in source and
binary forms, with or without modification, of the software and documentation
provided that the following conditions are met:
0. If you receive a version of the software that is specifically labelled
as not being for redistribution (check the version message and/or README),
you are not permitted to redistribute that version of the software in any
way or form.
1. All terms of the all other applicable copyrights and licenses must be
followed.
2. Redistributions of source code must retain the authors' copyright
notice(s), this list of conditions, and the following disclaimer.
3. Redistributions in binary form must reproduce the authors' copyright
notice(s), this list of conditions, and the following disclaimer in the
documentation and/or other materials provided with the distribution.
4. [The copyright holder has authorized the removal of this clause.]
5. Neither the name(s) of the author(s) nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY ITS AUTHORS AND CONTRIBUTORS ``AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
If these license terms cause you a real problem, contact the author. */
The file sunrpc/des_impl.c is copyright Eric Young:
Copyright (C) 1992 Eric Young
Collected from libdes and modified for SECURE RPC by Martin Kuck 1994
This file is distributed under the terms of the GNU Lesser General
Public License, version 2.1 or later - see the file COPYING.LIB for details.
If you did not receive a copy of the license with this program, please
see <http://www.gnu.org/licenses/> to obtain a copy.
The file inet/rcmd.c is under a UCB copyright and the following:
Copyright (C) 1998 WIDE Project.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the project nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
The file posix/runtests.c is copyright Tom Lord:
Copyright 1995 by Tom Lord
All Rights Reserved
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the name of the copyright holder not be
used in advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
Tom Lord DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
EVENT SHALL TOM LORD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
The posix/rxspencer tests are copyright Henry Spencer:
Copyright 1992, 1993, 1994, 1997 Henry Spencer. All rights reserved.
This software is not subject to any license of the American Telephone
and Telegraph Company or of the Regents of the University of California.
Permission is granted to anyone to use this software for any purpose on
any computer system, and to alter it and redistribute it, subject
to the following restrictions:
1. The author is not responsible for the consequences of use of this
software, no matter how awful, even if they arise from flaws in it.
2. The origin of this software must not be misrepresented, either by
explicit claim or by omission. Since few users ever read sources,
credits must appear in the documentation.
3. Altered versions must be plainly marked as such, and must not be
misrepresented as being the original software. Since few users
ever read sources, credits must appear in the documentation.
4. This notice may not be removed or altered.
The file posix/PCRE.tests is copyright University of Cambridge:
Copyright (c) 1997-2003 University of Cambridge
Permission is granted to anyone to use this software for any purpose on any
computer system, and to redistribute it freely, subject to the following
restrictions:
1. This software is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
2. The origin of this software must not be misrepresented, either by
explicit claim or by omission. In practice, this means that if you use
PCRE in software that you distribute to others, commercially or
otherwise, you must put a sentence like this
Regular expression support is provided by the PCRE library package,
which is open source software, written by Philip Hazel, and copyright
by the University of Cambridge, England.
somewhere reasonably visible in your documentation and in any relevant
files or online help data or similar. A reference to the ftp site for
the source, that is, to
ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/
should also be given in the documentation. However, this condition is not
intended to apply to whole chains of software. If package A includes PCRE,
it must acknowledge it, but if package B is software that includes package
A, the condition is not imposed on package B (unless it uses PCRE
independently).
3. Altered versions must be plainly marked as such, and must not be
misrepresented as being the original software.
4. If PCRE is embedded in any software that is released under the GNU
General Purpose Licence (GPL), or Lesser General Purpose Licence (LGPL),
then the terms of that licence shall supersede any condition above with
which it is incompatible.
Files from Sun fdlibm are copyright Sun Microsystems, Inc.:
Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
Developed at SunPro, a Sun Microsystems, Inc. business.
Permission to use, copy, modify, and distribute this
software is freely granted, provided that this notice
is preserved.
Various long double libm functions are copyright Stephen L. Moshier:
Copyright 2001 by Stephen L. Moshier <moshier@na-net.ornl.gov>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, see
<http://www.gnu.org/licenses/>. */
@@ -29,4 +29,12 @@
#define HWCAP_SSBS (1 << 28)
#define HWCAP_SB (1 << 29)
#define HWCAP_PACA (1 << 30)
#define HWCAP_PACG (1UL << 31)
#define HWCAP_PACG (1UL << 31)
#define HWCAP2_DCPODP (1 << 0)
#define HWCAP2_SVE2 (1 << 1)
#define HWCAP2_SVEAES (1 << 2)
#define HWCAP2_SVEPMULL (1 << 3)
#define HWCAP2_SVEBITPERM (1 << 4)
#define HWCAP2_SVESHA3 (1 << 5)
#define HWCAP2_SVESM4 (1 << 6)
@@ -1,14 +0,0 @@
struct ipc_perm {
key_t __ipc_perm_key;
uid_t uid;
gid_t gid;
uid_t cuid;
gid_t cgid;
mode_t mode;
unsigned short __ipc_perm_seq;
unsigned long __pad1;
unsigned long __pad2;
};
#define IPC_64 0
@@ -1,2 +0,0 @@
#define _POSIX_V6_LP64_OFF64 1
#define _POSIX_V7_LP64_OFF64 1
@@ -1,2 +0,0 @@
#undef __WORDSIZE
#define __WORDSIZE 64
@@ -281,6 +281,12 @@
#define __NR_io_uring_setup 425
#define __NR_io_uring_enter 426
#define __NR_io_uring_register 427
#define __NR_open_tree 428
#define __NR_move_mount 429
#define __NR_fsopen 430
#define __NR_fsconfig 431
#define __NR_fsmount 432
#define __NR_fspick 433
#define SYS_io_setup 0
#define SYS_io_destroy 1
@@ -564,4 +570,10 @@
#define SYS_pidfd_send_signal 424
#define SYS_io_uring_setup 425
#define SYS_io_uring_enter 426
#define SYS_io_uring_register 427
#define SYS_io_uring_register 427
#define SYS_open_tree 428
#define SYS_move_mount 429
#define SYS_fsopen 430
#define SYS_fsconfig 431
#define SYS_fsmount 432
#define SYS_fspick 433
+1 -1
View File
@@ -50,7 +50,7 @@
* On GCC 4.9 we may always include those headers. On older GCCs, we may do it only if CPU
* features used by them are enabled, so we need to check macros like __SSE__ or __MMX__ first.
*/
#if __MINGW_GNUC_PREREQ(4, 9)
#if __MINGW_GNUC_PREREQ(4, 9) || defined(__clang__)
#define __MINGW_FORCE_SYS_INTRINS
#endif
@@ -1,7 +1,7 @@
#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
|| defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
#define LONG_BIT 64
#define LONG_BIT 32
#endif
#define LONG_MAX 0x7fffffffffffffffL
#define LONG_MAX 0x7fffffffL
#define LLONG_MAX 0x7fffffffffffffffLL
@@ -0,0 +1,2 @@
#define _POSIX_V6_ILP32_OFFBIG 1
#define _POSIX_V7_ILP32_OFFBIG 1
@@ -0,0 +1,3 @@
#undef __WORDSIZE
#define __WORDSIZE 32
/* FIXME */
@@ -1,14 +1,16 @@
struct semid_ds {
struct ipc_perm sem_perm;
time_t sem_otime;
long __unused1;
time_t sem_ctime;
long __unused2;
#if __BYTE_ORDER == __LITTLE_ENDIAN
unsigned short sem_nsems;
char __sem_nsems_pad[sizeof(time_t)-sizeof(short)];
char __sem_nsems_pad[sizeof(long)-sizeof(short)];
#else
char __sem_nsems_pad[sizeof(time_t)-sizeof(short)];
char __sem_nsems_pad[sizeof(long)-sizeof(short)];
unsigned short sem_nsems;
#endif
time_t __unused3;
time_t __unused4;
long __unused3;
long __unused4;
};
@@ -0,0 +1,21 @@
/* copied from kernel definition, but with padding replaced
* by the corresponding correctly-sized userspace types. */
struct stat {
dev_t st_dev;
int __st_dev_padding;
long __st_ino_truncated;
mode_t st_mode;
nlink_t st_nlink;
uid_t st_uid;
gid_t st_gid;
dev_t st_rdev;
int __st_rdev_padding;
off_t st_size;
blksize_t st_blksize;
blkcnt_t st_blocks;
struct timespec st_atim;
struct timespec st_mtim;
struct timespec st_ctim;
ino_t st_ino;
};
+13 -1
View File
@@ -381,6 +381,12 @@
#define __NR_io_uring_setup 425
#define __NR_io_uring_enter 426
#define __NR_io_uring_register 427
#define __NR_open_tree 428
#define __NR_move_mount 429
#define __NR_fsopen 430
#define __NR_fsconfig 431
#define __NR_fsmount 432
#define __NR_fspick 433
#define __ARM_NR_breakpoint 0x0f0001
#define __ARM_NR_cacheflush 0x0f0002
@@ -771,4 +777,10 @@
#define SYS_pidfd_send_signal 424
#define SYS_io_uring_setup 425
#define SYS_io_uring_enter 426
#define SYS_io_uring_register 427
#define SYS_io_uring_register 427
#define SYS_open_tree 428
#define SYS_move_mount 429
#define SYS_fsopen 430
#define SYS_fsconfig 431
#define SYS_fsmount 432
#define SYS_fspick 433
+1 -3
View File
@@ -8,6 +8,4 @@ struct ipc_perm {
int __ipc_perm_seq;
long __pad1;
long __pad2;
};
#define IPC_64 0x100
};
@@ -0,0 +1 @@
#define IPC_STAT 2
+2 -2
View File
@@ -1,7 +1,7 @@
#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
|| defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
#define LONG_BIT 32
#define LONG_BIT 64
#endif
#define LONG_MAX 0x7fffffffL
#define LONG_MAX 0x7fffffffffffffffL
#define LLONG_MAX 0x7fffffffffffffffLL
+1 -2
View File
@@ -8,6 +8,5 @@ struct msqid_ds {
msglen_t msg_qbytes;
pid_t msg_lspid;
pid_t msg_lrpid;
unsigned long __pad1;
unsigned long __pad2;
unsigned long __unused[2];
};
+2 -2
View File
@@ -1,2 +1,2 @@
#define _POSIX_V6_ILP32_OFFBIG 1
#define _POSIX_V7_ILP32_OFFBIG 1
#define _POSIX_V6_LP64_OFF64 1
#define _POSIX_V7_LP64_OFF64 1
+1 -2
View File
@@ -1,3 +1,2 @@
#undef __WORDSIZE
#define __WORDSIZE 32
/* FIXME */
#define __WORDSIZE 64
+4 -6
View File
@@ -1,16 +1,14 @@
struct semid_ds {
struct ipc_perm sem_perm;
time_t sem_otime;
time_t __unused1;
time_t sem_ctime;
time_t __unused2;
#if __BYTE_ORDER == __LITTLE_ENDIAN
unsigned short sem_nsems;
char __sem_nsems_pad[sizeof(time_t)-sizeof(short)];
char __sem_nsems_pad[sizeof(long)-sizeof(short)];
#else
char __sem_nsems_pad[sizeof(time_t)-sizeof(short)];
char __sem_nsems_pad[sizeof(long)-sizeof(short)];
unsigned short sem_nsems;
#endif
time_t __unused3;
time_t __unused4;
long __unused3;
long __unused4;
};
+4 -7
View File
@@ -1,21 +1,18 @@
/* copied from kernel definition, but with padding replaced
* by the corresponding correctly-sized userspace types. */
struct stat {
dev_t st_dev;
int __st_dev_padding;
long __st_ino_truncated;
ino_t st_ino;
mode_t st_mode;
nlink_t st_nlink;
uid_t st_uid;
gid_t st_gid;
dev_t st_rdev;
int __st_rdev_padding;
unsigned long __pad;
off_t st_size;
blksize_t st_blksize;
int __pad2;
blkcnt_t st_blocks;
struct timespec st_atim;
struct timespec st_mtim;
struct timespec st_ctim;
ino_t st_ino;
unsigned __unused[2];
};
+5
View File
@@ -100,6 +100,11 @@ int posix_fallocate(int, off_t, off_t);
#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
#define AT_NO_AUTOMOUNT 0x800
#define AT_EMPTY_PATH 0x1000
#define AT_STATX_SYNC_TYPE 0x6000
#define AT_STATX_SYNC_AS_STAT 0x0000
#define AT_STATX_FORCE_SYNC 0x2000
#define AT_STATX_DONT_SYNC 0x4000
#define AT_RECURSIVE 0x8000
#define FAPPEND O_APPEND
#define FFSYNC O_SYNC
+3
View File
@@ -31,6 +31,9 @@ void globfree(glob_t *);
#define GLOB_NOESCAPE 0x40
#define GLOB_PERIOD 0x80
#define GLOB_TILDE 0x1000
#define GLOB_TILDE_CHECK 0x4000
#define GLOB_NOSPACE 1
#define GLOB_ABORTED 2
#define GLOB_NOMATCH 3
@@ -76,6 +76,7 @@
#define ETH_P_QINQ2 0x9200
#define ETH_P_QINQ3 0x9300
#define ETH_P_EDSA 0xDADA
#define ETH_P_DSA_8021Q 0xDADB
#define ETH_P_IFE 0xED3E
#define ETH_P_AF_IUCV 0xFBFB
+7 -4
View File
@@ -18,10 +18,12 @@ extern "C" {
struct sched_param {
int sched_priority;
int sched_ss_low_priority;
struct timespec sched_ss_repl_period;
struct timespec sched_ss_init_budget;
int sched_ss_max_repl;
int __reserved1;
struct {
time_t __reserved1;
long __reserved2;
} __reserved2[2];
int __reserved3;
};
int sched_get_priority_max(int);
@@ -47,6 +49,7 @@ int sched_yield(void);
#define CLONE_FS 0x00000200
#define CLONE_FILES 0x00000400
#define CLONE_SIGHAND 0x00000800
#define CLONE_PIDFD 0x00001000
#define CLONE_PTRACE 0x00002000
#define CLONE_VFORK 0x00004000
#define CLONE_PARENT 0x00008000
+5
View File
@@ -71,6 +71,11 @@ int posix_spawn_file_actions_addopen(posix_spawn_file_actions_t *__restrict, int
int posix_spawn_file_actions_addclose(posix_spawn_file_actions_t *, int);
int posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t *, int, int);
#if defined(_BSD_SOURCE) || defined(_GNU_SOURCE)
int posix_spawn_file_actions_addchdir_np(posix_spawn_file_actions_t *__restrict, const char *__restrict);
int posix_spawn_file_actions_addfchdir_np(posix_spawn_file_actions_t *, int);
#endif
#ifdef __cplusplus
}
#endif
+1
View File
@@ -152,6 +152,7 @@ int ptsname_r(int, char *, size_t);
char *ecvt(double, int, int *, int *);
char *fcvt(double, int, int *, int *);
char *gcvt(double, int, char *);
char *secure_getenv(const char *);
struct __locale_struct;
float strtof_l(const char *__restrict, char **__restrict, struct __locale_struct *);
double strtod_l(const char *__restrict, char **__restrict, struct __locale_struct *);
+1 -1
View File
@@ -22,6 +22,7 @@ extern "C" {
#endif
#include <bits/ipc.h>
#include <bits/ipcstat.h>
#define IPC_CREAT 01000
#define IPC_EXCL 02000
@@ -29,7 +30,6 @@ extern "C" {
#define IPC_RMID 0
#define IPC_SET 1
#define IPC_STAT 2
#define IPC_INFO 3
#define IPC_PRIVATE ((key_t) 0)
+2 -2
View File
@@ -25,9 +25,9 @@ typedef unsigned long msglen_t;
#define MSG_NOERROR 010000
#define MSG_EXCEPT 020000
#define MSG_STAT 11
#define MSG_STAT (11 | (IPC_STAT & 0x100))
#define MSG_INFO 12
#define MSG_STAT_ANY 13
#define MSG_STAT_ANY (13 | (IPC_STAT & 0x100))
struct msginfo {
int msgpool, msgmap, msgmax, msgmnb, msgmni, msgssz, msgtql;
+2 -2
View File
@@ -31,9 +31,9 @@ extern "C" {
#define _SEM_SEMUN_UNDEFINED 1
#define SEM_STAT 18
#define SEM_STAT (18 | (IPC_STAT & 0x100))
#define SEM_INFO 19
#define SEM_STAT_ANY 20
#define SEM_STAT_ANY (20 | (IPC_STAT & 0x100))
struct seminfo {
int semmap;
+2 -2
View File
@@ -33,9 +33,9 @@ extern "C" {
#define SHM_LOCK 11
#define SHM_UNLOCK 12
#define SHM_STAT 13
#define SHM_STAT (13 | (IPC_STAT & 0x100))
#define SHM_INFO 14
#define SHM_STAT_ANY 15
#define SHM_STAT_ANY (15 | (IPC_STAT & 0x100))
#define SHM_DEST 01000
#define SHM_LOCKED 02000
#define SHM_HUGETLB 04000
+2
View File
@@ -176,6 +176,7 @@ long syscall(long, ...);
int execvpe(const char *, char *const [], char *const []);
int issetugid(void);
int getentropy(void *, size_t);
extern int optreset;
#endif
#ifdef _GNU_SOURCE
@@ -188,6 +189,7 @@ char *get_current_dir_name(void);
int syncfs(int);
int euidaccess(const char *, int);
int eaccess(const char *, int);
ssize_t copy_file_range(int, off_t *, int, off_t *, size_t, unsigned);
#endif
#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
@@ -0,0 +1,2 @@
#define _POSIX_V6_ILP32_OFFBIG 1
#define _POSIX_V7_ILP32_OFFBIG 1
@@ -0,0 +1,11 @@
struct semid_ds {
struct ipc_perm sem_perm;
time_t sem_otime;
long __unused1;
time_t sem_ctime;
long __unused2;
unsigned short sem_nsems;
char __sem_nsems_pad[sizeof(long)-sizeof(short)];
long __unused3;
long __unused4;
};
@@ -0,0 +1,21 @@
/* copied from kernel definition, but with padding replaced
* by the corresponding correctly-sized userspace types. */
struct stat {
dev_t st_dev;
int __st_dev_padding;
long __st_ino_truncated;
mode_t st_mode;
nlink_t st_nlink;
uid_t st_uid;
gid_t st_gid;
dev_t st_rdev;
int __st_rdev_padding;
off_t st_size;
blksize_t st_blksize;
blkcnt_t st_blocks;
struct timespec st_atim;
struct timespec st_mtim;
struct timespec st_ctim;
ino_t st_ino;
};
@@ -418,6 +418,12 @@
#define __NR_io_uring_setup 425
#define __NR_io_uring_enter 426
#define __NR_io_uring_register 427
#define __NR_open_tree 428
#define __NR_move_mount 429
#define __NR_fsopen 430
#define __NR_fsconfig 431
#define __NR_fsmount 432
#define __NR_fspick 433
#define SYS_restart_syscall 0
#define SYS_exit 1
@@ -836,4 +842,10 @@
#define SYS_pidfd_send_signal 424
#define SYS_io_uring_setup 425
#define SYS_io_uring_enter 426
#define SYS_io_uring_register 427
#define SYS_io_uring_register 427
#define SYS_open_tree 428
#define SYS_move_mount 429
#define SYS_fsopen 430
#define SYS_fsconfig 431
#define SYS_fsmount 432
#define SYS_fspick 433
@@ -1,7 +1,7 @@
#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
|| defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
#define LONG_BIT 64
#define LONG_BIT 32
#endif
#define LONG_MAX 0x7fffffffffffffffL
#define LONG_MAX 0x7fffffffL
#define LLONG_MAX 0x7fffffffffffffffLL
@@ -0,0 +1,2 @@
#define _POSIX_V6_ILP32_OFFBIG 1
#define _POSIX_V7_ILP32_OFFBIG 1
@@ -1,14 +0,0 @@
struct semid_ds {
struct ipc_perm sem_perm;
time_t sem_otime;
time_t sem_ctime;
#if __BYTE_ORDER == __LITTLE_ENDIAN
unsigned short sem_nsems;
char __sem_nsems_pad[sizeof(time_t)-sizeof(short)];
#else
char __sem_nsems_pad[sizeof(time_t)-sizeof(short)];
unsigned short sem_nsems;
#endif
time_t __unused3;
time_t __unused4;
};
@@ -400,6 +400,12 @@
#define __NR_io_uring_setup 4425
#define __NR_io_uring_enter 4426
#define __NR_io_uring_register 4427
#define __NR_open_tree 4428
#define __NR_move_mount 4429
#define __NR_fsopen 4430
#define __NR_fsconfig 4431
#define __NR_fsmount 4432
#define __NR_fspick 4433
#define SYS_syscall 4000
#define SYS_exit 4001
@@ -802,4 +808,10 @@
#define SYS_pidfd_send_signal 4424
#define SYS_io_uring_setup 4425
#define SYS_io_uring_enter 4426
#define SYS_io_uring_register 4427
#define SYS_io_uring_register 4427
#define SYS_open_tree 4428
#define SYS_move_mount 4429
#define SYS_fsopen 4430
#define SYS_fsconfig 4431
#define SYS_fsmount 4432
#define SYS_fspick 4433
@@ -9,6 +9,4 @@ struct ipc_perm {
int __pad1;
unsigned long __unused1;
unsigned long __unused2;
};
#define IPC_64 0x100
};
@@ -1,14 +0,0 @@
struct semid_ds {
struct ipc_perm sem_perm;
time_t sem_otime;
time_t sem_ctime;
#if __BYTE_ORDER == __LITTLE_ENDIAN
unsigned short sem_nsems;
char __sem_nsems_pad[sizeof(time_t)-sizeof(short)];
#else
char __sem_nsems_pad[sizeof(time_t)-sizeof(short)];
unsigned short sem_nsems;
#endif
time_t __unused3;
time_t __unused4;
};
@@ -1,6 +1,3 @@
#include <string.h>
#include <bits/alltypes.h>
struct stat {
dev_t st_dev;
int __pad1[3];
@@ -330,6 +330,12 @@
#define __NR_io_uring_setup 5425
#define __NR_io_uring_enter 5426
#define __NR_io_uring_register 5427
#define __NR_open_tree 5428
#define __NR_move_mount 5429
#define __NR_fsopen 5430
#define __NR_fsconfig 5431
#define __NR_fsmount 5432
#define __NR_fspick 5433
#define SYS_read 5000
#define SYS_write 5001
@@ -662,4 +668,10 @@
#define SYS_pidfd_send_signal 5424
#define SYS_io_uring_setup 5425
#define SYS_io_uring_enter 5426
#define SYS_io_uring_register 5427
#define SYS_io_uring_register 5427
#define SYS_open_tree 5428
#define SYS_move_mount 5429
#define SYS_fsopen 5430
#define SYS_fsconfig 5431
#define SYS_fsmount 5432
#define SYS_fspick 5433
@@ -14,11 +14,19 @@ typedef __builtin_va_list __isoc_va_list;
#ifndef __cplusplus
#ifdef __WCHAR_TYPE__
#if defined(__NEED_wchar_t) && !defined(__DEFINED_wchar_t)
typedef __WCHAR_TYPE__ wchar_t;
#define __DEFINED_wchar_t
#endif
#else
#if defined(__NEED_wchar_t) && !defined(__DEFINED_wchar_t)
typedef long wchar_t;
#define __DEFINED_wchar_t
#endif
#endif
#endif
#if defined(__NEED_float_t) && !defined(__DEFINED_float_t)
@@ -9,6 +9,4 @@ struct ipc_perm {
int __pad1;
long long __pad2;
long long __pad3;
};
#define IPC_64 0x100
};
@@ -1,7 +1,7 @@
#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
|| defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
#define LONG_BIT 64
#define LONG_BIT 32
#endif
#define LONG_MAX 0x7fffffffffffffffL
#define LONG_MAX 0x7fffffffL
#define LLONG_MAX 0x7fffffffffffffffLL
@@ -0,0 +1,2 @@
#define _POSIX_V6_ILP32_OFFBIG 1
#define _POSIX_V7_ILP32_OFFBIG 1
@@ -0,0 +1,3 @@
#undef __WORDSIZE
#define __WORDSIZE 32
/* FIXME */
@@ -407,6 +407,12 @@
#define __NR_io_uring_setup 425
#define __NR_io_uring_enter 426
#define __NR_io_uring_register 427
#define __NR_open_tree 428
#define __NR_move_mount 429
#define __NR_fsopen 430
#define __NR_fsconfig 431
#define __NR_fsmount 432
#define __NR_fspick 433
#define SYS_restart_syscall 0
#define SYS_exit 1
@@ -816,4 +822,10 @@
#define SYS_pidfd_send_signal 424
#define SYS_io_uring_setup 425
#define SYS_io_uring_enter 426
#define SYS_io_uring_register 427
#define SYS_io_uring_register 427
#define SYS_open_tree 428
#define SYS_move_mount 429
#define SYS_fsopen 430
#define SYS_fsconfig 431
#define SYS_fsmount 432
#define SYS_fspick 433
@@ -1,10 +1,8 @@
struct pt_regs {
unsigned long gpr[32], nip, msr, orig_gpr3, ctr, link, xer, ccr, mq;
unsigned long trap, dar, dsisr, result;
};
struct user {
struct pt_regs regs;
struct {
unsigned long gpr[32], nip, msr, orig_gpr3, ctr, link, xer, ccr, mq;
unsigned long trap, dar, dsisr, result;
} regs;
unsigned long u_tsize, u_dsize, u_ssize;
unsigned long start_code, start_data, start_stack;
long signal;
@@ -9,6 +9,4 @@ struct ipc_perm {
int __pad1;
long long __pad2;
long long __pad3;
};
#define IPC_64 0x100
};
@@ -1,12 +0,0 @@
struct msqid_ds {
struct ipc_perm msg_perm;
time_t msg_stime;
time_t msg_rtime;
time_t msg_ctime;
unsigned long msg_cbytes;
msgqnum_t msg_qnum;
msglen_t msg_qbytes;
pid_t msg_lspid;
pid_t msg_lrpid;
unsigned long __unused[2];
};
@@ -1,2 +0,0 @@
#define _POSIX_V6_LP64_OFF64 1
#define _POSIX_V7_LP64_OFF64 1
@@ -1,13 +0,0 @@
#include <endian.h>
struct semid_ds {
struct ipc_perm sem_perm;
time_t sem_otime;
time_t sem_ctime;
#if __BYTE_ORDER == __BIG_ENDIAN
unsigned short __pad[3], sem_nsems;
#else
unsigned short sem_nsems, __pad[3];
#endif
unsigned long __unused[2];
};
@@ -379,6 +379,12 @@
#define __NR_io_uring_setup 425
#define __NR_io_uring_enter 426
#define __NR_io_uring_register 427
#define __NR_open_tree 428
#define __NR_move_mount 429
#define __NR_fsopen 430
#define __NR_fsconfig 431
#define __NR_fsmount 432
#define __NR_fspick 433
#define SYS_restart_syscall 0
#define SYS_exit 1
@@ -760,4 +766,10 @@
#define SYS_pidfd_send_signal 424
#define SYS_io_uring_setup 425
#define SYS_io_uring_enter 426
#define SYS_io_uring_register 427
#define SYS_io_uring_register 427
#define SYS_open_tree 428
#define SYS_move_mount 429
#define SYS_fsopen 430
#define SYS_fsconfig 431
#define SYS_fsmount 432
#define SYS_fspick 433
@@ -1,10 +1,8 @@
struct pt_regs {
unsigned long gpr[32], nip, msr, orig_gpr3, ctr, link, xer, ccr, softe;
unsigned long trap, dar, dsisr, result;
};
struct user {
struct pt_regs regs;
struct {
unsigned long gpr[32], nip, msr, orig_gpr3, ctr, link, xer, ccr, softe;
unsigned long trap, dar, dsisr, result;
} regs;
unsigned long u_tsize, u_dsize, u_ssize;
unsigned long start_code, start_data, start_stack;
long signal;
@@ -1,14 +0,0 @@
struct ipc_perm {
key_t __ipc_perm_key;
uid_t uid;
gid_t gid;
uid_t cuid;
gid_t cgid;
mode_t mode;
unsigned short __ipc_perm_seq;
unsigned long __pad1;
unsigned long __pad2;
};
#define IPC_64 0
@@ -1,9 +0,0 @@
struct semid_ds {
struct ipc_perm sem_perm;
time_t sem_otime;
time_t sem_ctime;
unsigned short sem_nsems;
char __sem_nsems_pad[sizeof(time_t)-sizeof(short)];
time_t __unused3;
time_t __unused4;
};
@@ -1,25 +0,0 @@
#define SHMLBA 4096
struct shmid_ds
{
struct ipc_perm shm_perm;
size_t shm_segsz;
time_t shm_atime;
time_t shm_dtime;
time_t shm_ctime;
pid_t shm_cpid;
pid_t shm_lpid;
unsigned long shm_nattch;
unsigned long __pad1;
unsigned long __pad2;
};
struct shminfo {
unsigned long shmmax, shmmin, shmmni, shmseg, shmall, __unused[4];
};
struct shm_info {
int __used_ids;
unsigned long shm_tot, shm_rss, shm_swp;
unsigned long __swap_attempts, __swap_successes;
};
@@ -6,46 +6,43 @@
# define SIGSTKSZ 8192
#endif
/* gregs[0] holds the program counter. */
typedef unsigned long __riscv_mc_gp_state[32];
struct __riscv_mc_f_ext_state {
unsigned int __f[32];
unsigned int __fcsr;
};
struct __riscv_mc_d_ext_state {
unsigned long long __f[32];
unsigned int __fcsr;
};
struct __riscv_mc_q_ext_state {
unsigned long long __f[64] __attribute__((aligned(16)));
unsigned int __fcsr;
unsigned int __reserved[3];
};
union __riscv_mc_fp_state {
struct __riscv_mc_f_ext_state __f;
struct __riscv_mc_d_ext_state __d;
struct __riscv_mc_q_ext_state __q;
};
typedef struct mcontext_t {
__riscv_mc_gp_state __gregs;
union __riscv_mc_fp_state __fpregs;
} mcontext_t;
#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
typedef unsigned long greg_t;
typedef unsigned long gregset_t[32];
struct __riscv_f_ext_state {
unsigned int f[32];
unsigned int fcsr;
};
struct __riscv_d_ext_state {
unsigned long long f[32];
unsigned int fcsr;
};
struct __riscv_q_ext_state {
unsigned long long f[64] __attribute__((aligned(16)));
unsigned int fcsr;
unsigned int reserved[3];
};
union __riscv_fp_state {
struct __riscv_f_ext_state f;
struct __riscv_d_ext_state d;
struct __riscv_q_ext_state q;
};
typedef union __riscv_fp_state fpregset_t;
typedef struct sigcontext {
typedef union __riscv_mc_fp_state fpregset_t;
struct sigcontext {
gregset_t gregs;
fpregset_t fpregs;
} mcontext_t;
#else
typedef struct {
unsigned long gregs[32];
unsigned long long fpregs[66];
} mcontext_t;
};
#endif
struct sigaltstack {
@@ -54,10 +51,10 @@ struct sigaltstack {
size_t ss_size;
};
typedef struct __ucontext
typedef struct ucontext_t
{
unsigned long uc_flags;
struct __ucontext *uc_link;
struct ucontext_t *uc_link;
stack_t uc_stack;
sigset_t uc_sigmask;
mcontext_t uc_mcontext;
@@ -273,6 +273,21 @@
#define __NR_pkey_mprotect 288
#define __NR_pkey_alloc 289
#define __NR_pkey_free 290
#define __NR_statx 291
#define __NR_io_pgetevents 292
#define __NR_rseq 293
#define __NR_kexec_file_load 294
#define __NR_pidfd_send_signal 424
#define __NR_io_uring_setup 425
#define __NR_io_uring_enter 426
#define __NR_io_uring_register 427
#define __NR_open_tree 428
#define __NR_move_mount 429
#define __NR_fsopen 430
#define __NR_fsconfig 431
#define __NR_fsmount 432
#define __NR_fspick 433
#define __NR_sysriscv __NR_arch_specific_syscall
#define __NR_riscv_flush_icache (__NR_sysriscv + 15)
#define SYS_io_setup 0
@@ -550,5 +565,19 @@
#define SYS_pkey_mprotect 288
#define SYS_pkey_alloc 289
#define SYS_pkey_free 290
#define SYS_statx 291
#define SYS_io_pgetevents 292
#define SYS_rseq 293
#define SYS_kexec_file_load 294
#define SYS_pidfd_send_signal 424
#define SYS_io_uring_setup 425
#define SYS_io_uring_enter 426
#define SYS_io_uring_register 427
#define SYS_open_tree 428
#define SYS_move_mount 429
#define SYS_fsopen 430
#define SYS_fsconfig 431
#define SYS_fsmount 432
#define SYS_fspick 433
#define SYS_sysriscv __NR_arch_specific_syscall
#define SYS_riscv_flush_icache (__NR_sysriscv + 15)
@@ -1,43 +1,5 @@
struct user_regs_struct {
unsigned long pc;
unsigned long ra;
unsigned long sp;
unsigned long gp;
unsigned long tp;
unsigned long t0;
unsigned long t1;
unsigned long t2;
unsigned long s0;
unsigned long s1;
unsigned long a0;
unsigned long a1;
unsigned long a2;
unsigned long a3;
unsigned long a4;
unsigned long a5;
unsigned long a6;
unsigned long a7;
unsigned long s2;
unsigned long s3;
unsigned long s4;
unsigned long s5;
unsigned long s6;
unsigned long s7;
unsigned long s8;
unsigned long s9;
unsigned long s10;
unsigned long s11;
unsigned long t3;
unsigned long t4;
unsigned long t5;
unsigned long t6;
};
struct user_fpregs_struct {
double f[32];
unsigned int fcsr;
};
#include <signal.h>
#define ELF_NGREG 32
typedef unsigned long elf_greg_t, elf_gregset_t[ELF_NGREG];
typedef struct user_fpregs_struct elf_fpregset_t;
typedef union __riscv_mc_fp_state elf_fpregset_t;
@@ -1,14 +0,0 @@
struct ipc_perm {
key_t __ipc_perm_key;
uid_t uid;
gid_t gid;
uid_t cuid;
gid_t cgid;
mode_t mode;
unsigned short __pad1;
unsigned short __ipc_perm_seq;
unsigned long __pad2;
unsigned long __pad3;
};
#define IPC_64 0x100
@@ -1,12 +0,0 @@
struct msqid_ds {
struct ipc_perm msg_perm;
time_t msg_stime;
time_t msg_rtime;
time_t msg_ctime;
unsigned long msg_cbytes;
msgqnum_t msg_qnum;
msglen_t msg_qbytes;
pid_t msg_lspid;
pid_t msg_lrpid;
unsigned long __unused[2];
};
@@ -1,2 +0,0 @@
#define _POSIX_V6_LP64_OFF64 1
#define _POSIX_V7_LP64_OFF64 1
@@ -1,2 +0,0 @@
#undef __WORDSIZE
#define __WORDSIZE 64
@@ -1,7 +0,0 @@
struct semid_ds {
struct ipc_perm sem_perm;
time_t sem_otime;
time_t sem_ctime;
unsigned short __pad[3], sem_nsems;
unsigned long __unused[2];
};
@@ -344,6 +344,12 @@
#define __NR_io_uring_setup 425
#define __NR_io_uring_enter 426
#define __NR_io_uring_register 427
#define __NR_open_tree 428
#define __NR_move_mount 429
#define __NR_fsopen 430
#define __NR_fsconfig 431
#define __NR_fsmount 432
#define __NR_fspick 433
#define SYS_exit 1
#define SYS_fork 2
@@ -690,4 +696,10 @@
#define SYS_pidfd_send_signal 424
#define SYS_io_uring_setup 425
#define SYS_io_uring_enter 426
#define SYS_io_uring_register 427
#define SYS_io_uring_register 427
#define SYS_open_tree 428
#define SYS_move_mount 429
#define SYS_fsopen 430
#define SYS_fsconfig 431
#define SYS_fsmount 432
#define SYS_fspick 433
@@ -1,13 +0,0 @@
struct ipc_perm {
key_t __ipc_perm_key;
uid_t uid;
gid_t gid;
uid_t cuid;
gid_t cgid;
mode_t mode;
int __ipc_perm_seq;
long __pad1;
long __pad2;
};
#define IPC_64 0
@@ -1,12 +0,0 @@
struct msqid_ds {
struct ipc_perm msg_perm;
time_t msg_stime;
time_t msg_rtime;
time_t msg_ctime;
unsigned long msg_cbytes;
msgqnum_t msg_qnum;
msglen_t msg_qbytes;
pid_t msg_lspid;
pid_t msg_lrpid;
unsigned long __unused[2];
};
@@ -1,2 +0,0 @@
#define _POSIX_V6_LP64_OFF64 1
#define _POSIX_V7_LP64_OFF64 1
@@ -0,0 +1,11 @@
struct semid_ds {
struct ipc_perm sem_perm;
time_t sem_otime;
long __unused1;
time_t sem_ctime;
long __unused2;
unsigned short sem_nsems;
char __sem_nsems_pad[sizeof(long)-sizeof(short)];
long __unused3;
long __unused4;
};
@@ -337,6 +337,12 @@
#define __NR_io_uring_setup 425
#define __NR_io_uring_enter 426
#define __NR_io_uring_register 427
#define __NR_open_tree 428
#define __NR_move_mount 429
#define __NR_fsopen 430
#define __NR_fsconfig 431
#define __NR_fsmount 432
#define __NR_fspick 433
#define SYS_read 0
#define SYS_write 1
@@ -676,4 +682,10 @@
#define SYS_pidfd_send_signal 424
#define SYS_io_uring_setup 425
#define SYS_io_uring_enter 426
#define SYS_io_uring_register 427
#define SYS_io_uring_register 427
#define SYS_open_tree 428
#define SYS_move_mount 429
#define SYS_fsopen 430
#define SYS_fsconfig 431
#define SYS_fsmount 432
#define SYS_fspick 433
+43
View File
@@ -0,0 +1,43 @@
With exception of certain parts that are prominently marked as being
in the Public Domain, BSD, or LGPL this Software is provided under the
Zope Public License (ZPL) Version 2.1.
Copyright (c) 2009 - 2013 by the mingw-w64 project
See the AUTHORS file for the list of contributors to the mingw-w64 project.
This license has been certified as open source. It has also been designated
as GPL compatible by the Free Software Foundation (FSF).
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions in source code must retain the accompanying copyright
notice, this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the accompanying
copyright notice, this list of conditions, and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
3. Names of the copyright holders must not be used to endorse or promote
products derived from this software without prior written permission
from the copyright holders.
4. The right to distribute this software or to use it for any purpose does
not give you the right to use Servicemarks (sm) or Trademarks (tm) of
the copyright holders. Use of them is covered by separate agreement
with the copyright holders.
5. If any files are modified, you must cause the modified files to carry
prominent notices stating that you changed the files and the date of
any change.
Disclaimer
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+65
View File
@@ -0,0 +1,65 @@
LIBRARY "bcrypt.dll"
EXPORTS
BCryptAddContextFunction
BCryptAddContextFunctionProvider
BCryptCloseAlgorithmProvider
BCryptConfigureContext
BCryptConfigureContextFunction
BCryptCreateContext
BCryptCreateHash
BCryptCreateMultiHash
BCryptDecrypt
BCryptDeleteContext
BCryptDeriveKey
BCryptDeriveKeyCapi
BCryptDeriveKeyPBKDF2
BCryptDestroyHash
BCryptDestroyKey
BCryptDestroySecret
BCryptDuplicateHash
BCryptDuplicateKey
BCryptEncrypt
BCryptEnumAlgorithms
BCryptEnumContextFunctionProviders
BCryptEnumContextFunctions
BCryptEnumContexts
BCryptEnumProviders
BCryptEnumRegisteredProviders
BCryptExportKey
BCryptFinalizeKeyPair
BCryptFinishHash
BCryptFreeBuffer
BCryptGenRandom
BCryptGenerateKeyPair
BCryptGenerateSymmetricKey
BCryptGetFipsAlgorithmMode
BCryptGetProperty
BCryptHashData
BCryptImportKey
BCryptImportKeyPair
BCryptKeyDerivation
BCryptOpenAlgorithmProvider
BCryptProcessMultiOperations
BCryptQueryContextConfiguration
BCryptQueryContextFunctionConfiguration
BCryptQueryContextFunctionProperty
BCryptQueryProviderRegistration
BCryptRegisterConfigChangeNotify
BCryptRegisterProvider
BCryptRemoveContextFunction
BCryptRemoveContextFunctionProvider
BCryptResolveProviders
BCryptSecretAgreement
BCryptSetAuditingInterface
BCryptSetContextFunctionProperty
BCryptSetProperty
BCryptSignHash
BCryptUnregisterConfigChangeNotify
BCryptUnregisterProvider
BCryptVerifySignature
GetAsymmetricEncryptionInterface
GetCipherInterface
GetHashInterface
GetRngInterface
GetSecretAgreementInterface
GetSignatureInterface
+125
View File
@@ -0,0 +1,125 @@
LIBRARY COMCTL32.dll
EXPORTS
MenuHelp
ShowHideMenuCtl
GetEffectiveClientRect
DrawStatusTextA
CreateStatusWindowA
CreateToolbar
CreateMappedBitmap
DPA_LoadStream
DPA_SaveStream
DPA_Merge
CreatePropertySheetPage
MakeDragList
LBItemFromPt
DrawInsert
CreateUpDownControl
InitCommonControls
CreatePropertySheetPageA
CreatePropertySheetPageW
CreateStatusWindow
CreateStatusWindowW
CreateToolbarEx
DestroyPropertySheetPage
DllGetVersion
DllInstall
DrawStatusText
DrawStatusTextW
FlatSB_EnableScrollBar
FlatSB_GetScrollInfo
FlatSB_GetScrollPos
FlatSB_GetScrollProp
FlatSB_GetScrollPropPtr
FlatSB_GetScrollRange
FlatSB_SetScrollInfo
FlatSB_SetScrollPos
FlatSB_SetScrollProp
FlatSB_SetScrollRange
FlatSB_ShowScrollBar
GetMUILanguage
ImageList_Add
ImageList_AddIcon
ImageList_AddMasked
ImageList_BeginDrag
ImageList_Copy
ImageList_Create
ImageList_Destroy
ImageList_DragEnter
ImageList_DragLeave
ImageList_DragMove
ImageList_DragShowNolock
ImageList_Draw
ImageList_DrawEx
ImageList_DrawIndirect
ImageList_Duplicate
ImageList_EndDrag
ImageList_GetBkColor
ImageList_GetDragImage
ImageList_GetFlags
ImageList_GetIcon
ImageList_GetIconSize
ImageList_GetImageCount
ImageList_GetImageInfo
ImageList_GetImageRect
ImageList_LoadImage
ImageList_LoadImageA
ImageList_LoadImageW
ImageList_Merge
ImageList_Read
ImageList_Remove
ImageList_Replace
ImageList_ReplaceIcon
ImageList_SetBkColor
ImageList_SetDragCursorImage
ImageList_SetFilter
ImageList_SetFlags
ImageList_SetIconSize
ImageList_SetImageCount
ImageList_SetOverlayImage
ImageList_Write
InitCommonControlsEx
InitMUILanguage
InitializeFlatSB
LoadIconMetric
PropertySheet
PropertySheetA
PropertySheetW
RegisterClassNameW
UninitializeFlatSB
_TrackMouseEvent
FreeMRUList
Str_SetPtrW
DSA_Create
DSA_Destroy
DSA_GetItem
DSA_GetItemPtr
DSA_InsertItem
DSA_SetItem
DSA_DeleteItem
DSA_DeleteAllItems
DPA_Create
DPA_Destroy
DPA_Grow
DPA_Clone
DPA_GetPtr
DPA_GetPtrIndex
DPA_InsertPtr
DPA_SetPtr
DPA_DeletePtr
DPA_DeleteAllPtrs
DPA_Sort
DPA_Search
DPA_CreateEx
DPA_EnumCallback
DPA_DestroyCallback
DSA_EnumCallback
DSA_DestroyCallback
CreateMRUListW
AddMRUStringW
EnumMRUListW
SetWindowSubclass
RemoveWindowSubclass
DefSubclassProc
TaskDialog
TaskDialogIndirect
+34
View File
@@ -0,0 +1,34 @@
;
; Exports of file comdlg32.dll
;
; Autogenerated by gen_exportdef
; Written by Kai Tietz, 2007
;
LIBRARY comdlg32.dll
EXPORTS
ChooseColorA
ChooseColorW
ChooseFontA
ChooseFontW
CommDlgExtendedError
FindTextA
FindTextW
GetFileTitleA
GetFileTitleW
GetOpenFileNameA
GetOpenFileNameW
GetSaveFileNameA
GetSaveFileNameW
LoadAlterBitmap
PageSetupDlgA
PageSetupDlgW
PrintDlgA
PrintDlgExA
PrintDlgExW
PrintDlgW
ReplaceTextA
ReplaceTextW
Ssync_ANSI_UNICODE_Struct_For_WOW
WantArrows
dwLBSubclass
dwOKSubclass

Some files were not shown because too many files have changed in this diff Show More